为什么我的 COM 工厂在程序生命周期内从未被释放?

发布于 2024-09-29 17:57:06 字数 691 浏览 4 评论 0原文

我有一个本机 C++ ATL 进程内 COM 服务器。一个单独的测试程序

  • 调用 CoInitialize()
  • 调用 CoCreateInstance(),然后
  • 对指针调用 Release()
  • 然后调用 CoUnitialize () 并退出。

如果我在 Visual C++ 调试器下运行测试程序,调试 CRT 会报告单个内存泄漏,并且每次分配编号都是相同的。

我使用分配挂钩并发现没有返回到堆的对象是类工厂对象。

因此,基本上会发生以下情况:

  • 程序调用 CoCreateInstance()
  • COM 内部调用 DllGetClassObject()
  • ATL 实例化工厂并将所有权传递给调用者(COM 内部)

,然后传递给工厂从未发布 - 我没有看到对类工厂的 Release() 的足够调用。

怎么了?这是 COM 运行时的缺陷吗?

I have a native C++ ATL in-proc COM server. A separate test program

  • calls CoInitialize(),
  • calls CoCreateInstance(), then
  • calls Release() on the pointer,
  • then calls CoUnitialize() and exits.

If I run the test program under Visual C++ debugger the debug CRT reports a single memory leak and each time the allocation number is the same.

I used an allocation hook and found out that the object not being returned to the heap is the class factory object.

So basically the following happens:

  • the program calls CoCreateInstance()
  • COM internally calls DllGetClassObject()
  • ATL instantiates the factory and passes ownership to the caller (COM internals)

and then the factory is never released - I don't see enough calls to Release() of the class factory.

What is happening? Is that a defect in COM runtime?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浪推晚风 2024-10-06 17:57:06

原来是ATL实现的问题。

服务器使用全局 CComModule 类实例。当调用 CComModule::DllClassObject() 时,它会创建一个类工厂实例并将其缓存在 CComModule 对象引用的映射中。所以实际上 CComModule 对象拥有类工厂。当 CComModule 析构函数运行时,它不会释放缓存的类工厂。

为了释放所有缓存的类工厂,应在卸载服务器之前调用 CComModule::Term() 方法。 IMO 实现此目的的最简洁方法是从 CComModule 派生并在派生类析构函数中调用 CComModule::Term()

Turns out it's a problem of ATL implementation.

The server uses a global CComModule class instance. When CComModule::DllClassObject() is called it creates a class factory instance and caches it in the map referenced by the CComModule object. So in fact CComModule object owns the class factory. When CComModule destructor runs it doesn't release cached class factories.

In order to release all cached class factories CComModule::Term() method should be called before the server is unloaded. IMO the cleanest way to achieve this is to derive from CComModule and call CComModule::Term() in the derived class destructor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文