如何清理 _variant_t
How to clean up _variant_t
我的泄漏检查器告诉我这个函数中有第二次机会异常。
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 BSTR 需要使用 SystemFreeString()
取消分配,这是在上面的代码中完成的,但由于此 BSTR 是 _variant_t
的成员,它有自己的析构函数来清理,在这种情况下,谁应该真正清理 bstrVal
成员?
inline _variant_t::~_variant_t() throw()
{
::VariantClear(this);
}
在我看来,这似乎试图再次清理已经被 SysFreeString()
清理的内存,导致异常? documentation 说它清除了变体,但不清楚它到底清除了什么,它是否也释放了 bstrVal
?
如果我删除调用 SysFreeString(vtFld.bstrVal);
这确实会删除第二次机会异常,但我真的想知道这是正确的做法,因为文档没有提供足够的信心。
variant_t
owns its data and uses the VariantClear()
清理函数:
The function clears a VARIANTARG by setting the vt field to VT_EMPTY. The current contents of the VARIANTARG are released first. If the vtfield is VT_BSTR, the string is freed. If the vtfield is VT_DISPATCH, the object is released. If the vt field has the VT_ARRAY bit set, the array is freed.
_variant_t
是一个负责内存管理的包装器。类似于_bstr_t
,它管理一个BSTR
;他们一起工作效果最好。与其手动设置 vt
字段和 bstrVal
值,不如使用 variant_t
构造函数或 operator=
。 _bstr_t
将分配 BSTR
所有权并将其传递给 _variant_t
。我不记得使用它的细节。只需在 MSDN 上查找详细信息。
_variant_t
超出范围时会自动清理其数据。您正在手动调用 SysFreeString()
,但您没有将 bstrVal
设置为 NULL 或之后将 vt
设置为 VT_EMPTY
。因此,当 variant_t
析构函数调用 VariantClear()
清理数据时,它会再次尝试释放 bstrVal
并崩溃。
所以,完全不要手动调用 SysFreeString()
。如果您需要手动重置 variant_t
,请改用其 Clear()
方法:
vtFld.Clear();
我的泄漏检查器告诉我这个函数中有第二次机会异常。
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 BSTR 需要使用 SystemFreeString()
取消分配,这是在上面的代码中完成的,但由于此 BSTR 是 _variant_t
的成员,它有自己的析构函数来清理,在这种情况下,谁应该真正清理 bstrVal
成员?
inline _variant_t::~_variant_t() throw()
{
::VariantClear(this);
}
在我看来,这似乎试图再次清理已经被 SysFreeString()
清理的内存,导致异常? documentation 说它清除了变体,但不清楚它到底清除了什么,它是否也释放了 bstrVal
?
如果我删除调用 SysFreeString(vtFld.bstrVal);
这确实会删除第二次机会异常,但我真的想知道这是正确的做法,因为文档没有提供足够的信心。
variant_t
owns its data and uses the VariantClear()
清理函数:
The function clears a VARIANTARG by setting the vt field to VT_EMPTY. The current contents of the VARIANTARG are released first. If the vtfield is VT_BSTR, the string is freed. If the vtfield is VT_DISPATCH, the object is released. If the vt field has the VT_ARRAY bit set, the array is freed.
_variant_t
是一个负责内存管理的包装器。类似于_bstr_t
,它管理一个BSTR
;他们一起工作效果最好。与其手动设置 vt
字段和 bstrVal
值,不如使用 variant_t
构造函数或 operator=
。 _bstr_t
将分配 BSTR
所有权并将其传递给 _variant_t
。我不记得使用它的细节。只需在 MSDN 上查找详细信息。
_variant_t
超出范围时会自动清理其数据。您正在手动调用 SysFreeString()
,但您没有将 bstrVal
设置为 NULL 或之后将 vt
设置为 VT_EMPTY
。因此,当 variant_t
析构函数调用 VariantClear()
清理数据时,它会再次尝试释放 bstrVal
并崩溃。
所以,完全不要手动调用 SysFreeString()
。如果您需要手动重置 variant_t
,请改用其 Clear()
方法:
vtFld.Clear();