COM

2013-03-14 49 views
8

ile özel durum güvenli bellek kullanımı COM kullanırken, kaynak yönetimi için genellikle ATL::CComPtr ve ATL::CComBSTR gibi ATL akıllı işaretçilerine güveniyorum. Ama aradığım yöntemlerden bazıları, serbest bırakmak zorunda olduğum tahsis edilen depolama birimine işaretçiyi döndürmek için çıkış parametrelerini kullanıyor. GetDisplayName dizesi bellek ayırır ve çıkış parametresi ile bir işaretçi dönerCOM

WCHAR *pszName = nullptr; 
if (SUCCEEDED(pShellItem->GetDisplayName(SIGDN_FILESYSPATH, &pszName))) { 
    DoSomething(pszName); 
    CoTaskMemFree(pszName); 
} 

Not olduğu: Örneğin. CoTaskMemFree ile bu belleği boşaltmanın sorumluluğu odur.

DoSomething bir istisna atarsa, yukarıdaki kod kaçak olacaktır. Bu tür sızıntıları önlemek için pszName için bir çeşit akıllı işaretçi kullanmak istiyorum, ancak API WCHAR**'u alır, bu yüzden bir işaretçinin adresinden nasıl bir şey iletebileceğimi bilmiyorum. Ben tahsis eden ben değilim, RAII kullanamam.

WCHAR *pszName = nullptr; 
if (SUCCEEDED(pShellItem->GetDisplayName(SIGDN_FILESYSPATH, &pszName))) { 
    std::unique_ptr<WCHAR, CoTaskMemDeleter> guard(pszName); 
    DoSomething(pszName); 
} 

çalışır: o zaman

struct CoTaskMemDeleter { 
    void operator()(void *p) { ::CoTaskMemFree(p); } 
}; 

Ve hemen böyle bir standart akıllı pointer döndü işaretçi atayın:

Ben Böyle bir deleter kullanım RRID yapabilir eğer Ancak, ekstra bir koruma değişkenini tanıtmak hataya eğilimli görünüyor. Örneğin, bu yaklaşım bırakılan belleğe işaret eden pszName'u bırakır, bu yüzden yanlışlıkla tekrar kullanmak kolaydır.

Çıkış parametresi tarafından döndürülen COM-sunucu ayrılan bellek için bir akıllı işaretçi veya RAII sarıcı kullanmanın daha temiz bir yolu var mı? ATL'nin sağladığı bir şeyi özlüyorum mu?

+0

Anıyı kendiniz boşaltmak konusunda ne kötü? Bana göre, başka bir şey yapma çabasına değmez. – evanmcdonnal

+0

@evanmcdonnal: İstisna güvenliği. –

cevap

11

ATL zaten kutunun dışında bu birine sahiptir:

CComHeapPtr<WCHAR> pszName; 
const HRESULT nResult = pShellItem->GetDisplayName(..., &pszName); 
// Hooray, pszName will be CoTaskMemFree'd for you on scope leave 
// via ~CComHeapPtr 

CHeapPtr benzer şekilde diğer kaynak releasers uygulamaya elde edilebilir. CComHeapPtr, MSDN documented class'dur.

+1

ATL belgelerinde CComHeapPtr'i gördüm, ancak 'CoTaskMemAlloc'/'Free'' 'CComAllocator'' kullanmanın farkında değildim. Bir sonraki tepkim, "Bu nasıl derlenir?", Çünkü & pszName'de "WCHAR **' yerine "CComHeapPtr *' görünür. Sonra, ATL işaretçi sınıflarının, yasak olduğunu düşündüğüm, ancak aslında sadece şiddetle tavsiye edilmediğini belirterek, 'operatör &' ün yükünü aşırı yüklediğini keşfettim. Bu aşırı yüklenme, bunları bir STL konteynırında tutmanızı da engeller. –

+0

Akıllı şablon sınıfı, imleç sarma ve şablon argümanından bir * * 'referans alarak" CComPtr "türüne benzemektedir:' IUnkown * ', CComPtr ' ile sarılmıştır ve 'WCHAR *', 'CHeapPtr tarafından sarılmıştır '. Evet, NULL olmayan işaretçiyi yeni işlenmemiş değeri kabul etmek için bir yer tutucu olarak göstermeye çalıştığınızda, her ikisi de, özellikle de onaylama yetkisini yükseltmek için aşırı yükleme yapıyor. –

+1

Sadece meraktan: Yazma operatörünü kim engelliyor? – StuartRedmann