2009-11-16 87 views

回答

4

忘記在應該的時候調用Release()。使用CComPtr <>,CComVARIANT <>和CComBSTR來幫助你。

7

無法爲COM對象使用RAII包裝類型。特別是不使用CComPtr<>,CComBSTRCComVARIANT<>。這些對象幫助通過消除從開發人員釋放底層資源的責任來防止泄漏。包裝對象強制釋放它的析構函數中的資源。

我看到的泄漏或意外的FreeS的另一個原因是從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並刪除,因爲臨時值超出了範圍。

2

有兩個主要原因:不使用RAII(智能指針)和誤用RAII。

如果您使用原始指針 - IInterface *或BSTR,則可能會忘記調用IInterface :: Release()或SysFreeString()並導致泄漏。如果您錯誤地使用智能指針,您也會冒內存泄漏的風險。一種方法是你提到的 - 將初始化的CComBSTR :: operator &()作爲[out]參數傳遞。還有其他一些方法,例如在禁用ATLASSERT的情況下將初始化智能指針的CComPtr :: operator &()或CCOmQIPtr :: operator &()作爲[out]參數傳遞。或者用一個循環創建任何類似圖形的結構,然後完全釋放它,這樣循環中的每個對象都會保持智能指針並防止釋放。