Question

I'm getting this unhandled exception when I exit my program:

Unhandled exception at 0x102fe274 (msvcr100d.dll) in Parameters.exe: 0xC0000005: Access violation reading location 0x00000005.

The debugger stops in a module called crtdll.c on this line:

onexitbegin_new = (_PVFV *) DecodePointer(__onexitbegin);

The top line on the call stack reads:

msvcr100d.dll!__clean_type_info_names_internal(__type_info_node * p_type_info_root_node=0x04a6506c) Line 359 + 0x3 bytes C++

The program then remains in memory until I close down the IDE.

I'm more used to developing with managed languages so I expect I'm doing something wrong with my code maintenance. The code itself reads a memory mapped file and assoiciates it with pointers:

SUBROUTINE READ_MMF ()
  USE IFWIN
  USE, INTRINSIC :: iso_c_binding
  USE, INTRINSIC :: iso_fortran_env 

  INTEGER(HANDLE) file_mapping_handle
  INTEGER(LPVOID) memory_location
  TYPE(C_PTR) memory_location_cptr
  INTEGER memory_size  
  INTEGER (HANDLE) file_map      
  CHARACTER(5)                   :: map_name 
  TYPE(C_PTR)                    :: cdata
  integer                        :: n = 3
  integer(4), POINTER            :: A, C
  real(8), POINTER               :: B

  TYPE STRUCT
    integer(4) :: A 
    real(8)    :: B
    integer(4) :: C
  END TYPE STRUCT
  TYPE(STRUCT), pointer :: STRUCT_PTR

  memory_size = 100000
  map_name = 'myMMF'

  file_map = CreateFileMapping(INVALID_HANDLE_VALUE,
 + NULL,
 + PAGE_READWRITE,
 + 0,
 + memory_size,
 + map_name // C_NULL_CHAR )  

  memory_location = MapViewOfFile(file_map,
 +IOR(FILE_MAP_WRITE, FILE_MAP_READ),
 + 0, 0, 0 )          

  cdata = TRANSFER(memory_location, memory_location_cptr)
  call c_f_pointer(cdata, STRUCT_PTR, [n]) 

  A => STRUCT_PTR%A
  B => STRUCT_PTR%B
  C => STRUCT_PTR%C

  RETURN
  END

Am I supposed to deallocate the c-pointers when I'm finished with them? I looked into that but can't see how I do it in Fortran...

Thanks for any help!

Was it helpful?

Solution

The nature of the access violation (during runtime library cleanup) suggests that your program is corrupting memory in some way. There are a number of programming errors that can lead to that - and the error or errors responsible could be anywhere in your program. The usual "compile and run with all diagnostic and debugging options enabled" approach may help identify these.

That said, there is a programming error in the code example shown. The C_F_POINTER procedure from the ISO_C_BINDING intrinsic module can operate on either scalar or array Fortran pointers (the second argument). If the Fortran pointer is a scalar then the third "shape" argument must not be present (it must be present if the Fortran pointer is an array).

Your code breaks this requirement - the Fortran pointer STRUCT_PTR in your code is a scalar, but yet you provide the third shape argument (as [n]). It is quite plausible that this error will result in memory corruption - typically the implementation of C_F_POINTER would try and populate a descriptor in memory for the Fortran pointer, and the descriptor for a pointer to an array may be very different from a pointer to a scalar.

Subsequent references to STRUCT_PTR may further the corruption.

While it is not required by the standard to diagnose this situation, I am a little surprised that the compiler does not issue a diagnostic (assuming you example code is what you actually are compiling). If you reported this to your compiler's vendor (Intel, presumably given IFWIN etc) I suspect they would regard it as a deficiency in their compiler.

To release the memory associated with the file mapping you use the UnmapViewOfFile and CloseHandle API's. To use these you should "store" (your program needs to remember in some way) the base address (memory_location, which can also be obtained by calling C_LOC on STRUCT_PTR once the problem above is fixed) returned by MapViewOfFile, and the handle to the mapping (file_map) returned by CreateFileMapping; respectively.

OTHER TIPS

I've only ever done this with Cray Pointers: not with the ISO bindings and I know it does work with Cray Pointers.

What you don't say is whether this is happening the first time or second time the routine is being called. If it is called more than once, then there is a problem in the coding in that Create/OpenFileMapping should only be called once to get a handle.

You don't need to deallocate memory because the memory is not yours to deallocate: you need to call UnmapViewOfFile(memory_location). After you have called this, memory_location, memory_location_cptr and possibly cdata are no longer valid.

The way this works is with two or more programs:

One program calls CreateFileMapping, the others calls OpenFileMapping to obtain a handle to the data. This only needs to be called once at the start of the program: not every time you need to access the file. Multiple calls to Create/OpenFileMapping without a corresponding close can cause crashes.

They then call MapViewOfFile to map the file into memory. Note that only one program can do this at a time. When the program is finished with the memory file, it calls UnmapViewOfFile. The other program can now get to the file. There is a blocking mechanism. If you do not call UnmapViewOfFile, other programs using MapViewOfFile will be blocked.

When all is done, call close on the handle created by Create/OpenFileMapping.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top