我的泄漏检查员告诉我这个功能有第二次机会异常。
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需要使用SystemFreeString()
取消分配BSTR,这是在上面的代码中完成的,但是因为这个BSTR是_variant_t
的成员,它有自己的析构函数来清理,在这种情况下谁应该真正清理bstrVal
成员?
inline _variant_t::~_variant_t() throw()
{
::VariantClear(this);
}
在我看来,这会尝试再次清理已由SysFreeString()
清除导致异常的内存? documentation表示它清除了变体,但目前尚不清楚它究竟是什么清除,它是否也释放了bstrVal
?
如果我删除了调用SysFreeString(vtFld.bstrVal);
,这确实会删除第二次机会异常,但我真的想知道这是正确的做法,因为文档没有给出足够的信心。
答案 0 :(得分:4)
_variant_t
在超出范围时自动清理其数据。您手动拨打SysFreeString()
,但未将bstrVal
设置为NULL或之后将vt
设置为VT_EMPTY
。因此,当variant_t
析构函数调用VariantClear()
来清理数据时,它会尝试再次释放bstrVal
并崩溃。
因此,根本不要手动调用SysFreeString()
。如果您需要手动重置variant_t
,请改用Clear()
方法:
vtFld.Clear();
答案 1 :(得分:2)
variant_t
拥有其数据并使用VariantClear()
函数进行清理:
该函数通过将vt字段设置为VT_EMPTY来清除VARIANTARG。 VARIANTARG的当前内容首先发布。 如果vtfield是VT_BSTR,则释放字符串。如果vtfield是VT_DISPATCH,则释放该对象。如果vt字段设置了VT_ARRAY位,则释放该数组。
_variant_t
是一个负责内存管理的包装器。与管理BSTR
的{{3}}类似;他们最好一起工作。不是手动设置vt
字段和bstrVal
值,而是使用variant_t
构造函数或operator=
更好。 _bstr_t
会将BSTR
所有权分配并传递给_variant_t
。我不记得使用它的细节。只需查看MSDN上的详细信息。