使用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