有人告訴我是一對夫婦,下面的代碼被泄漏內存工具,但我們不能讓我們的生命看到:哪裏是在該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變種因爲泄漏的大小與從記錄集返回的字符串的大小相匹配。我試過olevar.detach()和olevar.clear(),都沒有效果,所以如果這是原因,我該如何釋放大概在GetItem中分配的內存。如果這不是原因,那是什麼?
編輯
我讀到雷建議的文章,也與此相關的意見,然後嘗試:
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;
}
主要的區別在於olevariant和BSTR現在明確創建和銷燬。
這已經大致減半泄漏量,但仍有一些在這裏正在泄漏。
解決方案?
看着雷有關使用拆離的建議,我想出了這個:
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值。我沒有這個問題確切,但我有一段代碼導致內存泄漏。花了相當多的時間縮小到這行代碼。抱歉格式問題。 'void GetValue(COleVariant&oVar) { 。 。 。 //oVar.Clear(); - 如果bstr被分配給這個變體,沒有這個調用的話會因爲下一行而導致內存泄漏! oVar.Vt = VT_I4; oVar.lVal = 100; }' – Patel 2017-12-12 01:54:43