When using COM, I typically rely on ATL smart pointers, like ATL::CComPtr and ATL::CComBSTR, for resource management. 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. It's the caller's responsibility to free that memory with CoTaskMemFree.
If DoSomething throws an exception, then the above code will leak. 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. Since I'm not the one allocating, I can't use RAII.
I can use RRID if I can make a deleter like this:
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.
Is there a cleaner way to use a smart pointer or an RAII wrapper for COM-server allocated memory returned by output parameter? Am I missing something that ATL provides?