2

これは本当に頭が痛くなり始めています:(

相互運用しようとしているアンマネージ DLL がありますが、うまくいきません。アプリケーションが動作することもありますが、ほとんどの場合、ランダムに AccessViolationException が発生し、恐ろしくクラッシュします。

単一の DllImport の取り扱いミスに絞り込んだと思います。

C++ 関数:

HTMLRENDERERDLL_REDIST_API void SetDataBuffer( int windowHandle, unsigned char* dataSource, int format, int stride, int totalBufferSize );

C# DllImport:

[DllImport("MyDll.dll", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
    static private extern unsafe void SetDataBuffer(Int32 windowHandle, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] dataSource, Int32 format, Int32 stride, Int32 totalBufferSize);

上記の関数への呼び出し:

var buffer = new byte[windowWidth * windowHeight * bytesPerPixel];
SetDataBuffer(windowHandle, buffer, (Int32)0, (Int32)(windowWidth * bytesPerPixel), (Int32)(windowWidth * windowHeight * bytesPerPixel));

これに明らかに間違っていることはありますか?私はそれdataSourceが原因だと思いますが...それを証明する方法がわかりません!

ありがとう

4

2 に答える 2

2

問題は関数の名前から推測できます。「バッファを設定」すると、ネイティブ コードが後でそのバッファを使用する可能性があります。これはガベージ コレクターと互換性がありません。ヒープを圧縮するときに配列を移動します。ネイティブコードがバッファに書き込むとき、それは大きなカブームです。もう存在しないメモリに書き込むことになります。最も一般的な結果は、ヒープの整合性が損なわれたことをガベージ コレクターが検出したときの FatalExecutionEngineException です。

配列を固定する必要があります。これは、pinvoke マーシャラーが関数を呼び出すときに行うことですが呼び出し後に配列の固定を解除します。

GCHandle.Alloc() を使用してマネージ配列を固定できますが、長時間固定したままにしておくと、ガベージ コレクターにかなりの悪影響を及ぼします。断然最良の解決策は、Marshal.AllocHGlobal を使用してアンマネージ メモリのチャンクを割り当てることです。

それでも問題が解決しない場合は、バッファのサイズを心配してください。AccessViolation に陥るのに多くの助けが必要になることはめったにありません。これは、ネイティブ コードの標準的な失敗モードです。診断が非常に難しく、ソース コードがなければ不可能です。コード所有者にサポートを依頼し、問題の特定に役立つ小さな再現スニペットを用意してください。

于 2012-07-27T10:52:00.043 に答える
0

データソースが問題である可能性が高いことに同意します。

byte[] ではなく IntPtr を使用するように dllimport を変更してみてください。

[DllImport("MyDll.dll", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
static private extern unsafe void SetDataBuffer(Int32 windowHandle, IntPtr dataSource, Int32 format, Int32 stride, Int32 totalBufferSize);

次に、それを呼び出すときに、次のようにバッファにメモリを明示的に割り当てます。

IntPtr buffer = Marshal.AllocHGlobal(windowWidth * windowHeight * bytesPerPixel);
SetDataBuffer(windowHandle, buffer, (Int32)0, (Int32)(windowWidth * bytesPerPixel), (Int32)(windowWidth * windowHeight * bytesPerPixel));

そして、仕事が終わったら電話することを忘れないでくださいMarshal.FreeHGlobal(buffer)

バッファが Update メソッドによって内部的に使用されていると思いますか?

于 2012-07-27T09:51:31.180 に答える