假设我有以下代码在多线程 COM 应用程序的一个线程中运行:
// 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 最终消失时,我遇到了问题。我注意到在 Visual Studio 中调试 DoSomething 的地址不再能够被评估。在第一个线程死后,当我调用时:
myFooInThread2->DoSomething(&anotherParmPtr);
我遇到访问冲突。myFooInThread2 指针仍然有效,但函数指针无效。该函数指针是通过调用 loadUpFoo 设置的,而 loadUpFoo 又位于 LoadLibrary 加载的 dll 中。
我的问题是:我从哪里开始寻找失败的原因?外部 DLL(我使用 LoadLibrary 加载)在我的 foo 结构中设置函数指针的方式是否存在问题?还是与使用同一库的不同线程有关?或者,它是否与我在此应用程序中使用 COM 相关(在第一个线程中调用 CoUninitialize 会以某种方式释放此内存或库)?
如果看起来可能是负责任的,我可以提供有关 COM 设置的更多详细信息。谢谢!
编辑:感谢到目前为止的建议。foo 结构是不透明的——我不太了解它的实现。foo 结构在我导入的标头中声明。没有我明确调用的引用计数方法,也没有与使用 LoadLibrary 加载的库的其他交互。我很确定 foo 结构不是内存映射到某个 COM 类,但就像我说它是不透明的,我不能肯定地说。
foo 指针的生命周期得到妥善管理(未删除)。
foo 结构是一个加密库,所以我不能再泄露了。在这一点上,我确信我在不同线程和 COM 应用程序中使用 LoadLibrary 本质上没有任何问题(并且我认为函数指针内存清理是由库本身中的某些东西引起的,我无法控制)。