私は次のコードは、メモリをリークしているツールのカップルも言われているが、どこ私たちは私たちの生活のために見ることができない:私たちは、OLEVARバリアントとは何かであると仮定このC++のメモリリークはどこにありますか?
HRESULT CDatabaseValues::GetCStringField(ADODB::_RecordsetPtr& aRecordset, CString& strFieldValue,
const char* strFieldName, const bool& bNullAllowed)
{
HRESULT hr = E_FAIL;
try
{
COleVariant olevar;
olevar = aRecordset->Fields->GetItem(_bstr_t(strFieldName))->Value;
if (olevar.vt == VT_BSTR && olevar.vt != VT_EMPTY)
{
strFieldValue = olevar.bstrVal;
hr = true;
}
else if ((olevar.vt == VT_NULL || olevar.vt == VT_EMPTY) && bNullAllowed)
{
//ok, but still did not retrieve a field
hr = S_OK;
strFieldValue = "";
}
}
catch(Exception^ error)
{
hr = E_FAIL;
MLogger::Write(error);
}
return hr;
}
リークのサイズがレコードセットから返される文字列のサイズと一致するためです。
olevar.detach()とolevar.clear()はどちらも効果がありませんでした。これが原因であれば、おそらくGetItemに割り当てられているメモリを解放します。そして、これが原因でないなら、何がありますか?
EDIT
私はレイによって提案された記事を読み、またそれに関連するコメントや、その後試してみました:olevariantとBSTRいる
HRESULT CDatabaseValues::GetCStringField(ADODB::_RecordsetPtr& aRecordset, CString& strFieldValue,
const char* strFieldName, const bool& bNullAllowed)
{
HRESULT hr = E_FAIL;
try
{
COleVariant* olevar = new COleVariant();
_bstr_t* fieldName = new _bstr_t(strFieldName);
*olevar = aRecordset->Fields->GetItem(*fieldName)->Value;
if (olevar->vt == VT_BSTR && olevar->vt != VT_EMPTY)
{
strFieldValue = olevar->bstrVal;
hr = true;
}
else if ((olevar->vt == VT_NULL || olevar->vt == VT_EMPTY) && bNullAllowed)
{
//ok, but still did not retrieve a field
hr = S_OK;
strFieldValue = "";
}
delete olevar;
delete fieldName;
}
catch(Exception^ error)
{
hr = E_FAIL;
MLogger::Write(error);
}
return hr;
}
主な違いは、現在、明示的に作成および破棄されます。
これはリークの量を約半分にしましたが、ここに漏れているものがまだあります。
解決策?デタッチの使用についてのレイからアドバイスを見てみると
は、私はこの思い付いたん:
HRESULT CDatabaseValues::GetCStringField(ADODB::_RecordsetPtr& aRecordset, CString& strFieldValue,
const char* strFieldName, const bool& bNullAllowed)
{
HRESULT hr = E_FAIL;
try
{
COleVariant olevar;
_bstr_t fieldName = strFieldName;
olevar = aRecordset->Fields->GetItem(fieldName)->Value;
if (olevar.vt == VT_BSTR && olevar.vt != VT_EMPTY)
{
BSTR fieldValue = olevar.Detach().bstrVal;
strFieldValue = fieldValue;
::SysFreeString(fieldValue);
hr = true;
}
else if ((olevar.vt == VT_NULL || olevar.vt == VT_EMPTY) && bNullAllowed)
{
//ok, but still did not retrieve a field
hr = S_OK;
strFieldValue = "";
}
::SysFreeString(fieldName);
}
catch(Exception^ error)
{
hr = E_FAIL;
MLogger::Write(error);
}
return hr;
}
ツール(GlowCode)によれば、これはもはやリークしているが、私はfieldValueの上SysFreeStringのを使用して心配ですそれがCStringに割り当てられた後。それは実行されるように見えますが、私はそれが記憶腐敗が無料であるという指標ではないことを知っています!
私のポストは、BSTR値について考えさせてくれました。私は厳密にこの問題を抱えていませんでしたが、私はメモリリークを引き起こしたコードを次のように持っています。このコード行に絞るにはかなりの時間がかかりました。書式設定の問題で申し訳ありません。 'GetValue(COleVariant&oVar)void { 。 。 。 //oVar.Clear(); - この変種のためにbstrが割り当てられていた場合、この呼び出しがないと次の行のためメモリリークが発生する!! oVar.Vt = VT_I4; oVar.lVal = 100; } ' – Patel