マルチスレッド COM アプリケーションの 1 つのスレッドで実行される次のコードがあるとします。
// Thread 1
struct foo {
int (*DoSomething)(void ** parm);
};
HMODULE fooHandle = LoadLibrary("pathToFoo");
typedef int (*loadUpFooFP)(foo ** fooPtrPtr);
loadUpFooFP loadUpFoo;
loadUpFoo = (loadUpFooFP)GetProcAddress(fooHandle, "fooLoader");
foo * myFoo;
loadUpFoo(&myFoo);
これはすべてうまく機能し、電話をかけることができます
myFoo->DoSomething(&parmPtr);
これも機能します!ここで、別のスレッドがやって来て、その foo をロードします。
// Thread 2
foo * myFooInThread2;
loadUpFoo(&myFooInThread2);
そして、これもうまく機能します。スレッド 2 で DoSomething を呼び出すことができます。
// Thread 2
myFooInThread2->DoSomething(&anotherParmPtr);
さて、スレッド 1 が最終的になくなると、問題が発生します。DoSomething のアドレスが評価できなくなっていることを Visual Studio でデバッグしていることに気付きました。最初のスレッドが終了した後、私が呼び出すと:
myFooInThread2->DoSomething(&anotherParmPtr);
アクセス違反になります。myFooInThread2 ポインターは引き続き有効ですが、関数ポインターは有効ではありませんでした。この関数ポインタは、LoadLibrary によってロードされた dll にある loadUpFoo への呼び出しによって設定されました。
私の質問は次のとおりです。これが失敗する理由をどこから探し始めますか? 外部 DLL (LoadLibrary でロードする) が foo 構造体に関数ポインタを設定する方法に問題がありますか? それとも、同じライブラリを使用する異なるスレッドと関係がありますか? それとも、このアプリケーションでの COM の使用に関係している可能性があります (最初のスレッドで CoUninitialize を呼び出すと、このメモリまたはライブラリが何らかの形で解放されます)。
それが原因であると思われる場合は、COM セットアップの詳細を提供できます。ありがとう!
編集:これまでの提案に感謝します。foo 構造体は不透明です - 私はその実装についてあまり知りません。foo 構造体は、インポートするヘッダーで宣言されています。明示的に呼び出す参照カウント メソッドはなく、LoadLibrary で読み込まれたライブラリとの相互作用は他にありません。foo 構造体が一部の COM クラスにマップされたメモリではないことは確かですが、前述のように不透明であり、確かなことは言えません。
foo ポインターの有効期間は適切に管理されます (削除されません)。
foo 構造は暗号化ライブラリであるため、これ以上公開することはできません。この時点で、異なるスレッド間および COM アプリケーション内での LoadLibrary の使用に本質的に問題はないと確信しています (また、関数ポインター メモリのクリーンアップは、ライブラリ自体の制御外の何かによって引き起こされていると思います)。 )。