使用COM時,我通常依靠ATL智能指針(如ATL::CComPtr
和ATL::CComBSTR
)進行資源管理。但是我調用的一些方法使用輸出參數來返回指向我必須釋放的分配存儲的指針。例如:使用COM的異常安全內存處理
WCHAR *pszName = nullptr;
if (SUCCEEDED(pShellItem->GetDisplayName(SIGDN_FILESYSPATH, &pszName))) {
DoSomething(pszName);
CoTaskMemFree(pszName);
}
注意GetDisplayName
的字符串分配內存,並通過輸出參數返回一個指向它的指針。來電者的責任是用CoTaskMemFree
釋放該內存。
如果DoSomething
引發異常,則上面的代碼將會泄漏。我想用pszName
的某種智能指針來避免這種泄漏,但API需要WCHAR**
,所以我沒有看到如何通過除啞指針地址之外的任何東西。由於我不是分配的人,所以我不能使用RAII。
我可以使用RRID如果我能做出這樣的缺失者:
struct CoTaskMemDeleter {
void operator()(void *p) { ::CoTaskMemFree(p); }
};
然後返回的指針立即分配到一個標準的智能指針這樣的:
WCHAR *pszName = nullptr;
if (SUCCEEDED(pShellItem->GetDisplayName(SIGDN_FILESYSPATH, &pszName))) {
std::unique_ptr<WCHAR, CoTaskMemDeleter> guard(pszName);
DoSomething(pszName);
}
這一工程,但似乎很容易引入額外的防護變量。例如,這種方法將pszName
指向釋放的內存,所以很容易再次意外地使用它。
是否有更清晰的方式來使用智能指針或RAII包裝器爲輸出參數返回的COM服務器分配的內存?我錯過ATL提供的東西嗎?
自己釋放記憶有什麼不好?對我來說,做任何事情似乎都不值得。 – evanmcdonnal 2013-03-14 20:40:05
@evanmcdonnal:例外安全。 – 2013-03-14 21:01:07