CComPtr<T>是一個(gè)ATL中的一個(gè)智能指針類型,它及它的派生類CComQIPtr<T>為我們提供了智能管理COM接口指針的能力。 也就是在析構(gòu)時(shí)自動(dòng)釋放資源的工具類,這些工具類能有效地幫助我們杜絕內(nèi)存泄漏、句柄沒(méi)有釋放之類錯(cuò)誤。她們是很智能、很聰明,不過(guò)這要我們寫(xiě)出正確的程式,如果使用不正確也會(huì)出現(xiàn)上述這些問(wèn)題。往往內(nèi)存泄漏、句柄沒(méi)有釋放這些錯(cuò)誤很難一下調(diào)試出來(lái),多數(shù)是通過(guò)工具來(lái)檢查出來(lái)。有的工具對(duì)智能指針的誤用也是較難發(fā)現(xiàn)。
下面是我經(jīng)歷過(guò)的一個(gè)場(chǎng)景:
[
object,
uuid(….),
….
]
Interface IA
{
…
};
//Client;
Class B
{
IA GetIA(..);
};
B b;
CComPtr<IA> aPtr(b.GetIA(…));
這樣導(dǎo)致我的一個(gè)結(jié)構(gòu)化存儲(chǔ)資源被長(zhǎng)久地占用,不能刪除。有人或許已經(jīng)知道問(wèn)題的所在了。這個(gè)錯(cuò)誤就在于CComPtr<IA> aPtr(b.GetIA(…));這樣從方法傳出來(lái)的接口就沒(méi)有能夠調(diào)用Release,這樣泄漏就產(chǎn)生了。正確的使用應(yīng)如下
CComPtr<IA> aPtr;
aPtr.Attach(b.GetIA(…));
拿出這兩個(gè)方法的源代碼就非常清楚了。
CComPtrBase(_In_opt_ T* lp) throw()
{
p = lp;
if (p != NULL)
p->AddRef();
}
void Attach(_In_opt_ T* p2) throw()
{
if (p)
p->Release();
p = p2;
}
對(duì)于Detach和析構(gòu)方法不會(huì)因混亂造成問(wèn)題,因?yàn)镈etach總是用于一個(gè)方法中要返回一個(gè)智能指針的實(shí)際接口時(shí)調(diào)用從而達(dá)到使代碼簡(jiǎn)潔。而析構(gòu)也會(huì)因?yàn)榉蛛x出了接口指針而不做任何事情。