有人告诉我是一对夫妇,下面的代码被泄漏内存工具,但我们不能让我们的生命看到:哪里是在该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