我的泄漏检查程序告诉我此功能有第二次机会异常。

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);,这确实会删除第二次机会异常,但是我真的想知道那是正确的做法,因为文档没有给予足够的信心。

最佳答案

_variant_t超出范围时会自动清除其数据。您正在手动调用SysFreeString(),但是之后没有将bstrVal设置为NULL或将vt设置为VT_EMPTY。因此,当variant_t析构函数调用VariantClear()清理数据时,它将尝试再次释放bstrVal并崩溃。

因此,根本不需要手动调用SysFreeString()。如果您需要手动重置variant_t,请改用其Clear()方法:

vtFld.Clear();

10-01 13:25