void InSomewhere(IHello* pHello) {
CComPtr spHello = pHello;
spHello->DoSomething();
hr = CoCreateInstance(CLSID_HELLO, NULL, CLSCTX_INPROC_SERVER,
IID_IHELLO, (void**)&spHello); // 危險:spHello 非空
assert(SUCCEEDED(hr));
spHello->DoOtherthing();
}
spHello 原有指向,取位址操作行為未定義:
• CComPtr:Debug 斷言,Release 靜默洩漏;
• _com_ptr_t:悄悄釋放原資源,無任何警告。
spHello.CoCreateInstance(CLSID_HELLO); // 仍只是 Debug 斷言,Release 洩漏
void InSomewhere(IHello* pHello) {
CComPtr spHello = pHello;
spHello->DoSomething();
spHello = NULL; // 或 spHello.Release() —— 手動提前釋放
spHello.CoCreateInstance(CLSID_HELLO);
assert(spHello);
spHello->DoOtherthing();
}
template
class MyStack {
T* m_pArray; int m_nTop, m_nCapacity;
void push(T Item) { m_pArray[m_nTop++] = Item; }
T pop() { return m_pArray[--m_nTop]; } // 未清理原位置!
};
MyStack> g_myStack(1000);
void func() {
for (int i=0; i<500; i++) {
CComPtr sp = NULL;
sp.CoCreateInstance(CLSID_CALCULATOR);
g_myStack.push(sp); // 複製進容器,引用計數 +1
}
// ...
for (int i=0; i<500; i++) {
CComPtr sp = g_myStack.pop(); // 取出但容器原位置未清理
sp->DoSomething();
}
} // 容器後半部 500 個智能指標永不釋放 → 洩漏
原因:智能指標在全域空間,等待 ~MyStack() 需到程式結束。pop() 後容器仍持有引用,若後續元素不滿 500,後半部資源永不釋放。
T pop() {
assert(m_nTop > 0);
T temp = m_pArray[--m_nTop];
m_pArray[m_nTop] = NULL; // 或 m_pArray[m_nTop].Release();
return temp;
}
銘記:智能指標僅輔助管理記憶體,**必須提前釋放 COM 資源時,別妄想智能指標幫你完成**。
—— 作者:liuchang5 的專欄