COM内存泄漏最常见的原因是什么?
我已经读过将初始化的CComBSTR的地址作为[out]参数传递给函数会导致泄漏。我想列举其他常见的编程错误。
答案 0 :(得分:7)
未能为COM对象使用RAII包装类型。特别是不使用CComPtr<>
,CComBSTR
和CComVARIANT<>
。这些对象 help 通过消除从开发人员释放底层资源的责任来防止泄漏。包装对象强制在其析构函数中释放资源。
我看到的泄漏或意外释放的另一个原因是从CComPtr<T>
到T*
的隐式转换。这对于将包装对象作为参数传递很有用。但它可能会导致问题,因为它允许RAII对象和原始指针之间的隐式转换。例如
CComPtr<IFoo> GetAFoo(); // Imagine if this creates the object
...
IFoo* pFoo = GetAFoo();
pFoo->SomeCall();
在这种情况下,对SomeCall的调用可能会失败,因为此时对象pFoo已经死了。为什么?返回值为GetAFoo的ref计数为1,分配给pFoo,然后递减为0并删除,因为临时值超出范围。
答案 1 :(得分:4)
忘记在应该的时候调用Release()。使用CComPtr&lt;&gt;,CComVARIANT&lt;&gt;和CComBSTR来帮助你。
答案 2 :(得分:2)
主要有两个原因:不使用RAII(智能指针)和滥用RAII。
如果您使用原始指针--Interface *或BSTR,您可能会忘记调用IInterface :: Release()或SysFreeString(),这将导致泄漏。如果您错误地使用智能指针,也会导致内存泄漏。一种方法是你提到的那个 - 将初始化的CComBSTR :: operator&amp;()作为[out]参数传递。还有其他方法,例如将初始化智能指针的CComPtr :: operator&amp;()或CCOmQIPtr :: operator&amp;()作为[out]参数传递,禁用ATLASSERT。或者使用循环创建任何类似图形的结构并完全释放它,以便循环中的对象每个都保持智能指针并防止释放。