0

当我退出我的程序时,我得到了这个未处理的异常:

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

调试器在此行的名为 crtdll.c 的模块中停止:

onexitbegin_new = (_PVFV *) DecodePointer(__onexitbegin);

调用堆栈的第一行内容如下:

msvcr100d.dll!__clean_type_info_names_internal(__type_info_node * p_type_info_root_node=0x04a6506c) 第 359 行 + 0x3 字节 C++

然后程序会一直保留在内存中,直到我关闭 IDE。

我更习惯于使用托管语言进行开发,所以我希望我的代码维护有问题。代码本身读取内存映射文件并将其与指针关联:

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

当我完成它们时,我应该释放 c 指针吗?我调查了一下,但看不到我在 Fortran 中是如何做到的......

谢谢你的帮助!

4

2 回答 2

2

访问冲突的性质(在运行时库清理期间)表明您的程序正在以某种方式破坏内存。有许多编程错误可能导致这种情况 - 并且负责的错误或错误可能出现在您的程序中的任何地方。通常的“在启用所有诊断和调试选项的情况下编译和运行”方法可能有助于识别这些。

也就是说,显示的代码示例中存在编程错误。ISO_C_BINDING 内部模块中的 C_F_POINTER 过程可以对标量或数组 Fortran 指针(第二个参数)进行操作。如果 Fortran 指针是标量,则第三个“shape”参数不得存在(如果 Fortran 指针是数组,则必须存在)。

您的代码打破了这一要求 - 代码中的 Fortran 指针STRUCT_PTR是一个标量,但您提供了第三个 shape 参数(as [n])。这个错误很可能会导致内存损坏 - 通常 C_F_POINTER 的实现会尝试在内存中填充 Fortran 指针的描述符,并且指向数组的指针的描述符可能与指向标量的指针非常不同.

随后的引用STRUCT_PTR可能会进一步破坏。

虽然标准不需要诊断这种情况,但我有点惊讶编译器没有发出诊断(假设您的示例代码是您实际正在编译的)。如果您将此报告给编译器的供应商(英特尔,大概是 IFWIN 等),我怀疑他们会将其视为编译器的缺陷。

要释放与文件映射关联的内存,请使用 UnmapViewOfFile 和 CloseHandle API。要使用这些,您应该“存储”(您的程序需要以某种方式记住)由 MapViewOfFile 返回的基memory_location地址STRUCT_PTRfile_map) 由 CreateFileMapping 返回;分别。

于 2013-03-28T20:05:36.970 回答
1

我只用 Cray 指针做过这个:不是用 ISO 绑定,我知道它确实适用于 Cray 指针。

您没有说的是这是第一次还是第二次调用例程时发生这种情况。如果它被多次调用,那么编码中存在问题,因为 Create/OpenFileMapping 应该只被调用一次以获得句柄。

你不需要释放内存,因为内存不是你要释放的:你需要调用 UnmapViewOfFile(memory_location)。在您调用它之后,memory_location、memory_location_cptr 和可能的 cdata 不再有效。

它的工作方式是使用两个或多个程序:

一个程序调用 CreateFileMapping,其他程序调用 OpenFileMapping 来获取数据的句柄。这只需要在程序开始时调用一次:而不是每次您需要访问文件时。在没有相应关闭的情况下多次调用 Create/OpenFileMapping 可能会导致崩溃。

然后他们调用 MapViewOfFile 将文件映射到内存中。请注意,一次只有一个程序可以执行此操作。当程序处理完内存文件后,它会调用 UnmapViewOfFile。另一个程序现在可以访问该文件。有一个阻塞机制。如果不调用 UnmapViewOfFile,其他使用 MapViewOfFile 的程序将被阻塞。

完成后,在 Create/OpenFileMapping 创建的句柄上调用 close。

于 2013-03-29T08:17:45.547 回答