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-pointer の使用が終わったら、その c-pointer の割り当てを解除する必要がありますか? 私はそれを調べましたが、Fortranでそれを行う方法がわかりません...

助けてくれてありがとう!

4

2 に答える 2

2

アクセス違反の性質 (ランタイム ライブラリのクリーンアップ中) は、プログラムが何らかの方法でメモリを破損していることを示唆しています。その原因となるプログラミング エラーは多数あります。また、原因となるエラーはプログラムのどこにでもある可能性があります。通常の「すべての診断およびデバッグ オプションを有効にしてコンパイルおよび実行する」アプローチは、これらの特定に役立つ場合があります。

とはいえ、示されているコード例にはプログラミング エラーがあります。ISO_C_BINDING 組み込みモジュールの C_F_POINTER プロシージャーは、スカラーまたは配列の Fortran ポインター (2 番目の引数) を操作できます。Fortran ポインターがスカラーの場合、3 番目の「形状」引数は存在してはなりません (Fortran ポインターが配列の場合は存在する必要があります)。

コードはこの要件を破っています。コード内の Fortran ポインターSTRUCT_PTRはスカラーですが、3 番目の shape 引数 (as [n]) を指定します。このエラーがメモリの破損を引き起こす可能性は非常に高いです - 通常、C_F_POINTER の実装はメモリ内に Fortran ポインタの記述子を作成しようとし、配列へのポインタの記述子はスカラーへのポインタとは大きく異なる場合があります。 .

への後続の参照STRUCT_PTRは、破損を促進する可能性があります。

標準ではこの状況を診断する必要はありませんが、コンパイラが診断を発行しないことに少し驚いています (サンプル コードが実際にコンパイルしているものであると仮定すると)。これをコンパイラのベンダー (Intel、おそらく IFWIN など) に報告した場合、コンパイラの欠陥と見なされるのではないかと思います。

ファイル マッピングに関連付けられたメモリを解放するには、UnmapViewOfFile および CloseHandle API を使用します。これらを使用するには、MapViewOfFile によって返されたベース アドレス (上記の問題が修正されたらmemory_locationC_LOC を呼び出して取得することもできますSTRUCT_PTR) と、マッピングへのハンドル ( file_map) CreateFileMapping によって返されます。それぞれ。

于 2013-03-28T20:05:36.970 に答える
1

ISOバインディングではなく、Cray Pointersでのみこれを行ったことがあります.Cray Pointersで機能することはわかっています。

あなたが言わないのは、これがルーチンが呼び出されるのが初めてなのか、それとも 2 回目なのかということです。複数回呼び出される場合は、ハンドルを取得するために Create/OpenFileMapping を 1 回だけ呼び出す必要があるというコーディング上の問題があります。

メモリは割り当てを解除するものではないため、メモリの割り当てを解除する必要はありません。UnmapViewOfFile(memory_location) を呼び出す必要があります。これを呼び出すと、memory_location、memory_location_cptr、および場合によっては cdata が無効になります。

これが機能する方法は、2 つ以上のプログラムを使用する場合です。

1 つのプログラムは CreateFileMapping を呼び出し、他のプログラムは OpenFileMapping を呼び出してデータへのハンドルを取得します。これは、プログラムの開始時に 1 回だけ呼び出す必要があります。ファイルにアクセスする必要があるたびに呼び出す必要はありません。対応するクローズなしで Create/OpenFileMapping を複数回呼び出すと、クラッシュが発生する可能性があります。

次に、MapViewOfFile を呼び出して、ファイルをメモリにマップします。一度にこれを実行できるプログラムは 1 つだけであることに注意してください。プログラムがメモリ ファイルの処理を終了すると、UnmapViewOfFile を呼び出します。他のプログラムがファイルにアクセスできるようになりました。ブロック機構があります。UnmapViewOfFile を呼び出さない場合、MapViewOfFile を使用する他のプログラムはブロックされます。

すべてが完了したら、Create/OpenFileMapping によって作成されたハンドルで close を呼び出します。

于 2013-03-29T08:17:45.547 に答える