2012-07-09 4 views
8

管理対象コールバックをアンマネージドTCPレシーバに渡す必要があります。アプリケーションの存続期間中に存在する必要があるスレッドなので、ガベージコレクションが行われないようにする必要があります。私はどこにでも関数ポインタを固定する必要はなく、GCHandle.Allocはガベージコレクションを防止するという仕事をしています。関数ポインタをピンに固定

これは指定されていますか?私はこのコードをホストしているAppPoolがアクセス違反でクラッシュするのを見ました。関数ポインタがガベージコレクションされたためにこのエラーが発生するという事実は疑わしくありませんか?

このpostは、この事実をサポートしています。

更新: これはクラッシュを大幅に軽減したようです。このアプローチに問題はありますか?

typedef void (__cdecl *ProcMessageFunc)(void* param, void* paramBuf, ULONG bufSize); 
FuncDelegate^ fp = gcnew MessageFuncDelegate(this, &Handler); 
pin_ptr<MessageFuncDelegate^> pinnedFunctionPointer = &fp; 
ret = Receiver ((ProcMessageFunc)pinnedFunctionPointer); 
+3

静的変数にデリゲートオブジェクトを格納するだけで十分です。ネイティブコードは、他の多くの理由でアクセス違反で爆弾攻撃を受けることがあります。 –

+0

私はそれを正確にしました。ガベージコレクションが原因であると疑われる傾向にある理由は、アクセス違反が不規則に発生するためです。そしてもっと重要なのは、クラッシュダンプ内のコールスタックです。ネイティブdllとそれに続く、clr.dll、次にkernel32.dllがスタックの先頭に表示されます。この順序は一貫しています。 – Krishter

答えて

8

私はあなたが行うことをお勧め正確に何をすべきか - デリゲートではなく無ピニングとGCHandle.Allocを - と2.0多くの異なるプラットフォーム上で広範囲に使用されているすべての問題を抱えていたと.NETのバージョンにしていない - 4.サムシング以下のような:FunctionPointer

DelegateHandle = GCHandle.Alloc(xlDelegate); 
FunctionPointer = Marshal.GetFunctionPointerForDelegate(xlDelegate); 

は、ネイティブコードに渡され、DelegateHandleは、後にクリーンアップのために保存しました。

これは最も参考になると思われる:http://msdn.microsoft.com/en-us/library/367eeye0(v=vs.80).aspx

あなたが指すポストの何もこのリファレンスと矛盾しています。ガベージコレクションからデリゲートを保護する必要があります。ピン割り当ては不要です

+0

ヒープオブジェクトとは異なり、constの場所に存在するため、機能のアドレス固定は不要ですか? JITされていないのであれば、どのアドレスに関数がありますか? – Dai

+2

GetFunctionPointerForDelegateの呼び出しは、固定エントリーポイントを持つ小さなマーシャリングスタブを作成すると思いますが、デリゲートが移動された場合、スタブはそれを呼び出す方法をまだ知っています。したがって、エクスポートされた関数ポインタは、デリゲートオブジェクトのアドレスの直接的なエクスポートではありません(ピン配列や構造体メンバとは異なります)。エクスポートされた 'ネイティブ'関数もネイティブ - >管理されたトランジションを実装する必要があることに注意してください。 – Govert

+0

これはまさに私がやったことです。残念ながら、アクセス違反がまだ発生します。私にそれをこのようにしてみましょう。これがアクセス違反の原因ではないことを完全にどのように確信できますか? – Krishter

関連する問題