如何清理_variant_t

时间:2016-08-25 22:05:03

标签: c++ com variant

我的泄漏检查员告诉我这个功能有第二次机会异常。

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

2 个答案:

答案 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上的详细信息。