我的泄漏检查器告诉我在这个函数中有第二次机会异常。
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
(。我们知道BSTR需要使用SystemFreeString()
来取消分配,这是上面代码中所做的,但由于这个BSTR是_variant_t
的成员,它有自己的析构函数来清理,在这种情况下,谁应该真正清理bstrVal
成员?
inline _variant_t::~_variant_t() throw()
{
::VariantClear(this);
}
在我看来,这似乎试图再次清理已经被SysFreeString()
清理过的内存,导致异常?文件说它清除了变体,但不清楚它到底清除了什么,它也释放了bstrVal
吗?
如果我删除调用SysFreeString(vtFld.bstrVal);
,这确实会删除第二次机会异常,但我真的想知道这是正确的做法,因为文档没有提供足够的信心。
_variant_t
在超出范围时自动清理其数据。您正在手动调用SysFreeString()
,但之后不会将bstrVal
设置为NULL或将vt
设置为VT_EMPTY
。因此,当variant_t
析构函数调用VariantClear()
来清理数据时,它试图再次释放bstrVal
并崩溃。
因此,根本不要手动调用SysFreeString()
。如果您需要手动重置variant_t
,请使用其Clear()
方法:
vtFld.Clear();
variant_t
拥有其数据并使用VariantClear()
函数进行清理:
该函数通过将vt字段设置为vt_EMPTY来清除VARIANTARG。VARIANTARG的当前内容首先发布如果vtfield是VT_BSTR,则字符串被释放。如果vtfield为VT_DISPATCH,则对象将被释放。如果vt字段设置了vt_ARRAY位,则阵列将被释放。
CCD_ 22是一个负责内存管理的包装器。类似于管理BSTR
的_bstr_t
;他们合作得最好。与其手动设置vt
字段和bstrVal
值,不如使用variant_t
构造函数或operator=
。CCD_ 29将分配CCD_ 30所有权并将其传递给CCD_ 31。我不记得使用它的详细信息了。只需在MSDN上查找详细信息即可。