私は非常に奇妙な問題を抱えています:
NUnit を使用してアンマネージ C dll への関数呼び出しをいくつかテストしています。奇妙なことに、正常に実行するとテストは失敗しますが、デバッガーで実行すると (ブレークポイントがなくても) 正常に合格します。
では、デバッガーはプレーンな NUnit アプリケーションよりも広いメモリ アクセスを持っていますか?
失敗した呼び出しを分離しました。マーシャラーが C# 文字列に変換する必要がある文字列への char ポインターを返します。C 側は次のようになります。
#define get_symbol(a) ((a).a_w.w_symbol->s_name)
EXTERN char *atom_get_symbol(t_atom *a);
...
char *atom_get_symbol(t_atom *a) {
return get_symbol(*a);
}
および C# コード:
[DllImport("csharp.dll", EntryPoint="atom_get_symbol")]
[return:MarshalAs(UnmanagedType.LPStr)]
private static extern string atom_get_symbol(IntPtr a);
c から返されるポインターは、コード内の非常に深い部分とリストの一部です。だから私はいくつかのセキュリティ設定を見逃していますか?
編集:ここに私が得る例外があります:
System.AccessViolationException : (英語に翻訳:) 保護されたメモリを読み書きしようとしました。これは、他のメモリが破損していることを示している可能性があります。
at Microsoft.Win32.Win32Native.CoTaskMemFree(IntPtr ptr)
at ....atom_get_symbol(IntPtr a)
解決:
問題は、マーシャラーが C 構造体の一部であるメモリを解放したかったことです。ただし、文字列のコピーを作成して、メモリをそのままにしておく必要があります。
[DllImport("csharp.dll", EntryPoint="atom_get_symbol")]
private static extern IntPtr atom_get_symbol(IntPtr a);
次に、コードで次の文字列のコピーを取得します。
var string = Marshal.PtrToStringAnsi(atom_get_symbol(ptrToStruct));
すごい!