6

リーク チェッカーは、次のコードで割り当てられているメモリにメモリ リークがあることを示しています。

// Get the value from the object as a variant.
VARIANT vVal;
VariantInit ( &vVal );
hres = clsObj->Get ( fieldName.c_str(), 0, &vVal, 0, 0 );
if ( FAILED ( hres ) )
{
    (... various cleanup / throw stuff ...)
}

// And get it as a wstring.
wstring val ( vVal.bstrVal );

(... do some standard, non-memory leaking stuff with the wstring ...)    

// Clean up.
VariantClear ( &vVal );

そこにある「clsObj」は、WMI 用の Microsoft インターフェイスである IWbemClassObject です。

リークしたメモリを割り当てる特定の行は、「clsObj->Get」行です。次に、リーク チェッカーは、ソース コードを持っていないリーク自体のより具体的なコードを報告します (つまり、リークしたメモリの割り当て時のスタック トレース内)。

(ole32): (filename not available): CoRevokeMallocSpy    
(OLEAUT32): (filename not available): GetErrorInfo  
(OLEAUT32): (filename not available): SysAllocStringLen 
(OLEAUT32): (filename not available): SysAllocString    
(wbemcomn): (filename not available): CVar::SetBSTR 
(wbemcomn): (filename not available): CVar::FillVariant 
(fastprox): (filename not available): CWbemObject::Get  

そのため、VARIANT vVal の基になる BSTR がリークされているようです。しかし、私は VariantClear を行っています...他に何かする必要がありますか?

おそらく、wstringコンストラクターでリークしていますか?でも、もしそうなら、私にはわかりません。私は、bstrVal は基本的に char ポインター (または wchar など) に要約されると考えました。wstring コンストラクターは、他のポインターであるかのように、そのアドレスからコピーする必要がありますよね?

wstring コンストラクターが vVal.bstrVal によって最初に指されたメモリをクリアする責任を引き継ぐようなものではありません。参照カウントされた COM オブジェクトに対して Detach() を実行しているかのようです。

重要な場合、これは Visual C++ 6 にあります。

4

2 に答える 2

2

漏れはないかも!Microsoft の Larry Osterman によるこの記事を参照してください。

大量のリークを見つけて修正しましたが、BSTR オブジェクトを割り当てるたびに、特定できなかったリークの 1 つが表示されました。[...]

基本的に、OLE はプロセスに割り当てられたすべての BSTR オブジェクトをキャッシュして、文字列を一緒にプールできるようにします。その結果、これらの文字列は「意図的に」効果的にリークされます。[...]

幸いなことに、BSTR キャッシュを無効にする方法があります。アプリケーションを起動する前に、OANOCACHE 環境変数を 1 に設定するだけです。アプリケーションがサービスの場合、OANOCACHE をシステム環境変数 (環境変数の一番下のセット) として設定し、再起動する必要があります。
于 2013-01-10T05:32:53.753 に答える
0

ABSTRは 2 つのデータ要素です。これはint、基本ストリングの長さのカウントと、基本ストリングも含まれる です。したがって、空のBSTR保持がある場合でも、新しい値を""割り当てる前に適切に空にする必要があります。BSTRそうしないと、「文字列」部分を解放しても、intデータ メンバーが漏れてしまいます。

fieldname.c_str() をリークしていると思われます。おそらくBSTRスタック上に を作成しており、それが漏れています。

代わりにこれを行うようにコードを変更します。

CComBSTR tempBSTR = fieldName.c_str();
hres = clsObj->Get ( tempBSTR, 0, &vVal, 0, 0 );

これにより、少なくとも、BSTRGet() の呼び出しで自動ビルドがリークしていないことを確認できます。

ところで、 を使用する必要がある場合は、代わりBSTRに を使用CComBSTRすることを検討してください。これは、基本的なメモリ リークを防ぐのに役立ちます。

于 2013-01-09T20:18:21.393 に答える