COMを使用する場合、私は通常、リソース管理にATL::CComPtr
andなどのATLスマートポインターを使用します。ATL::CComBSTR
しかし、私が呼び出しているメソッドのいくつかは、出力パラメーターを使用して、解放する必要のある割り当てられたストレージへのポインターを返します。例えば:
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
では解放されたメモリをポイントしたままになるため、誤って再度使用する可能性があります。
出力パラメータによって返されるCOMサーバーに割り当てられたメモリにスマートポインタまたはRAIIラッパーを使用するよりクリーンな方法はありますか?ATLが提供するものが欠けていますか?