简体   繁体   English

使用COM进行异常安全的内存处理

[英]Exception-safe memory handling with COM

When using COM, I typically rely on ATL smart pointers, like ATL::CComPtr and ATL::CComBSTR , for resource management. 使用COM时,我通常依赖ATL智能指针,如ATL::CComPtrATL::CComBSTR ,进行资源管理。 But some of the methods I'm calling use output parameters to return pointers to allocated storage that I have to free. 但是我正在调用的一些方法使用输出参数来返回指向我必须释放的已分配存储的指针。 For example: 例如:

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

Note that GetDisplayName allocates memory for the string and returns a pointer to it through the output parameter. 请注意, GetDisplayName为字符串分配内存,并通过输出参数返回指向它的指针。 It's the caller's responsibility to free that memory with CoTaskMemFree . 调用者有责任使用CoTaskMemFree释放内存。

If DoSomething throws an exception, then the above code will leak. 如果DoSomething抛出异常,则上述代码将泄漏。 I'd like to use some sort of smart pointer for pszName to avoid such leaks, but the API takes WCHAR** , so I don't see how I can pass anything but the address of a dumb pointer. 我想为pszName使用某种智能指针来避免这种泄漏,但是API需要WCHAR** ,所以我看不出除了哑指针的地址之外我怎么能传递。 Since I'm not the one allocating, I can't use RAII. 由于我不是那个分配,我不能使用RAII。

I can use RRID if I can make a deleter like this: 如果我可以像这样制作一个删除器,我可以使用RRID:

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

And then immediately assign the returned pointer to a standard smart pointer like this: 然后立即将返回的指针分配给标准智能指针,如下所示:

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

That works, but it seems error-prone to introduce an extra guard variable. 这样可行,但似乎容易引入额外的保护变量。 For example, this approach leaves pszName pointing at the released memory, so it would be easy to accidentally use it again. 例如,这种方法使pszName指向释放的内存,因此很容易意外地再次使用它。

Is there a cleaner way to use a smart pointer or an RAII wrapper for COM-server allocated memory returned by output parameter? 对于输出参数返回的COM服务器分配的内存,是否有更简洁的方法来使用智能指针或RAII包装器? Am I missing something that ATL provides? 我错过了ATL提供的东西吗?

ATL already has this one out of the box: ATL已经开箱即用:

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

CHeapPtr can be derived to implement other resource releasers in a similar way. 可以派生CHeapPtr以类似的方式实现其他资源释放器。 CComHeapPtr is a MSDN documented class . CComHeapPtrMSDN记录的类

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM