2016-08-25 17 views
0

私のリークチェッカーは、この機能に2回目のチャンスの例外があると伝えます。クリーンアップの方法_variant_t

BOOL CADORecordset::SetFieldValue(LPCTSTR lpFieldName, CString strValue) 
{ 
    _variant_t vtFld; 

    if(!strValue.IsEmpty()) 
     vtFld.vt = VT_BSTR; 
    else 
     vtFld.vt = VT_NULL; 

    vtFld.bstrVal = strValue.AllocSysString(); 

    BOOL bret = PutFieldValue(lpFieldName, vtFld); 
    SysFreeString(vtFld.bstrVal); 

    return bret; 
} 

_variant_t型BSTR部材(bstrVal)を有しています。我々はknow BSTRは上記のコードで行われているSystemFreeString()を使用してBSTRを割り当て解除する必要があるが、このBSTRは_variant_tのメンバであり、この場合は誰が実際にbstrValメンバをクリーンアップする必要がある?

inline _variant_t::~_variant_t() throw() 
{ 
    ::VariantClear(this); 
} 

すでに例外を発生させSysFreeString()によってクリーンアップされ、再びメモリをクリーンアップしようとするように私には見えますか? documentationはそのバリアントをクリアすると言いますが、正確に何がクリアされるのかはっきりしません。bstrValも解放されますか?

SysFreeString(vtFld.bstrVal);のコールを削除すると、2回目のチャンス例外が削除されますが、ドキュメントが十分な信頼を与えないため、これが正しいことを知りたいのです。

+0

、決して良いアイデア:あなたは手動でvariant_tをリセットする必要がある場合は、代わりにそのClear()メソッドを使用します。 BSTRは、あなたから一度、variant_tによって一度削除されています* 2回*。フィールドにもアクセスしないでください。必要なのは '_variant_t vtFld(strValue);または' vtFld = strValue; '、restはオートマティックです。 –

+0

@HansPassant: 'strValue'が空のときには' PutFieldValue() 'に' VT_NULL'を渡す必要があるので、代わりに以下のようなものを使う方が正しいでしょう: '_variant_t vtFld; if(!strValue.IsEmpty())vtFld = strValue;それ以外はvtFld。vt = VT_NULL;戻り値PutFieldValue(lpFieldName、vtFld); ' –

答えて

4

_variant_tは、範囲外になると自動的にデータをクリーンアップします。手動でSysFreeString()を呼び出していますが、bstrValをNULLに設定していないか、またはその後にvtVT_EMPTYに設定していません。したがって、variant_tデストラクタがVariantClear()を呼び出してデータをクリーンアップすると、再びbstrValを解放しようとし、クラッシュします。

したがって、SysFreeString()を手動で呼び出さないでください。 `_variant_t`のようなラッパークラスを使用すると、あまりにも完全に支援している

vtFld.Clear(); 
2

variant_tは、そのデータを所有し、クリーンアップのためのVariantClear()機能を使用しています。

関数がVT_EMPTYにVTフィールドを設定することにより、VARIANTARGをクリアします。 VARIANTARGの現在の内容が最初に解放されます。 vtフィールドがVT_BSTRの場合、文字列は解放されます。 vtフィールドがVT_DISPATCHの場合、オブジェクトは解放されます。 vtフィールドにVT_ARRAYビットが設定されている場合、配列は解放されます。

_variant_tは、メモリ管理を担当するラッパーです。 BSTRを管理する_bstr_tと同様です。彼らは一番よく一緒に働く。 vtフィールドとbstrVal値を手動で設定する代わりに、variant_tコンストラクタまたはoperator=を使用することをお勧めします。 _bstr_tBSTRの所有権を割り当てて_variant_tに渡します。私はそれを使用する詳細を覚えていません。 MSDNで詳細を調べるだけです。

+0

私は実際にその構造体やVARIANTARGにあまり慣れていない多くのバリアントで作業していませんが、それはBSTRの権利を解放し、 'SysFreeString(vtFld.bstrVal);を呼び出さなければならない? – zar

+1

いいえ、あなたは 'SysFreeString()'を呼び出す必要はありません、 'variant_t'は' BSTR'を所有しています。 –

+1

Cをお持ちの場合、手動でリソースを管理する必要があります。 C++の特別なクラス '_variant_t'、' _bstr_t'と配列用のものが用意されています。 – monkeyman79

関連する問題