0

我最近遇到了一个COM使用单例类工厂的对象的问题,该对象的成员是指向在与单例对象不同的 DLL 中实现的其他 COM 对象的指针。

这些其他 COM 对象是由单例对象创建的,这是对它们的唯一引用。

由于单例对象在其模块被卸载之前永远不会被销毁,似乎正在发生的事情是有时在那个点上,实现其他 COM 对象(单例的成员)的 DLL 已经被卸载,在这种情况下会有当单例在其析构函数中释放对这些对象的引用时发生崩溃。

实现其他 COM 对象的 DLL 知道存在对对象的引用并S_FALSE从其DllCanUnloadNow方法返回。

但是,这似乎并不能阻止 DLL 总是被卸载。

是否有任何安全的方法可以在单例 COM 对象中保留来自另一个 dll 的 COM 对象的成员指针?

4

4 回答 4

1

您很可能正遭受“错误”的模块卸载顺序的困扰。请参阅为什么以“错误”的顺序卸载 DLL?了解更多信息。

于 2009-02-04T23:30:33.850 回答
0

如果您有一个指向 COM 对象的指针(也称为“保持引用”),那么该 COM 对象在您释放它之前不会消失。

如果尚未释放 COM 对象,则不应卸载实现其代码的 DLL:请参阅DllCanUnloadNow

于 2009-02-04T23:23:51.180 回答
0

当单例获取 COM 接口的实现时,应该在获取到的指针上的实现上调用 IUnknown::AddRef。

当您访问包含这些引用的单例字段时也是如此。获得引用后,应调用 IUnknown::AddRef,然后在完成后调用 IUnknown::Release。

这样,如果单例被回收并且它持有的所有指针都被释放,如果您在另一段代码中持有其中一个,您将不会丢失实例,因为您增加了引用计数。

您还应该考虑使用CComPtr 模板来帮助管理引用计数:

http://msdn.microsoft.com/en-us/library/ezzw7k98(vs.80).aspx

您可能还想查看引用计数的规则,您必须遵守这些规则:

http://msdn.microsoft.com/en-us/library/ms810016.aspx

查找标题为“引用计数规则”的部分

于 2009-02-04T23:51:01.050 回答
0

假设 Jeff Stong 是对的,请尝试以下方法之一:

  • 不要释放 COM 对象(让它泄漏)。

  • 创建从包含单例的 DLL 到包含 COM 对象的 DLL 的链接时(不仅仅是运行时)依赖项。

  • 在进程开始死亡和 DLL 开始被强制卸载之前,告诉单例死亡和/或释放 COM 对象。

于 2009-02-05T00:39:56.473 回答