C ++泄漏VARIANT / bstrVal代码

时间:2013-01-09 19:56:40

标签: c++ com memory-leaks variant bstr

泄漏检查程序告诉我内存中存在内存泄漏,该代码在以下代码中分配:

// Get the value from the object as a variant.
VARIANT vVal;
VariantInit ( &vVal );
hres = clsObj->Get ( fieldName.c_str(), 0, &vVal, 0, 0 );
if ( FAILED ( hres ) )
{
    (... various cleanup / throw stuff ...)
}

// And get it as a wstring.
wstring val ( vVal.bstrVal );

(... do some standard, non-memory leaking stuff with the wstring ...)    

// Clean up.
VariantClear ( &vVal );

“clsObj”中有一个IWbemClassObject,它是WMI内容的Microsoft接口。

分配泄漏内存的特定行是“clsObj-> Get”行。然后泄漏检查器报告泄漏本身的更具体的代码(即,在分配泄漏的内存时的堆栈跟踪中的更多内容),我没有源代码:

(ole32): (filename not available): CoRevokeMallocSpy    
(OLEAUT32): (filename not available): GetErrorInfo  
(OLEAUT32): (filename not available): SysAllocStringLen 
(OLEAUT32): (filename not available): SysAllocString    
(wbemcomn): (filename not available): CVar::SetBSTR 
(wbemcomn): (filename not available): CVar::FillVariant 
(fastprox): (filename not available): CWbemObject::Get  

因此看起来,VARIANT vVal中的潜在BSTR正在泄露。但我正在做一个VariantClear ......我还要做别的吗?

也许我在wstring构造函数中泄漏了它?但如果是这样,我不明白。我认为bstrVal基本上只归结为char指针(或wchar或其他); wstring构造函数应该只是从该地址复制,就像它是任何其他指针一样,对吧?

这不像wstring构造函数接管清理vVal.bstrVal最初指向的内存的责任,就像它在某个引用计数的COM对象上执行Detach()一样,是吗?

如果重要,这是在Visual C ++ 6中。

2 个答案:

答案 0 :(得分:1)

可能没有泄漏!请参阅this article by Microsoft's Larry Osterman on the subject,其中描述的内容类似于您所看到的内容:

我找到了一堆泄漏并修复了它们,但每次我们分配一个BSTR对象时,其中一个我想不通的漏洞就出现了。 [...]

基本上,OLE缓存进程中分配的所有BSTR对象,以允许它将字符串汇集在一起​​。结果,这些字符串“故意”有效地泄露。 [...]

幸运的是,有一种方法可以禁用BSTR缓存,只需在启动应用程序之前将OANOCACHE环境变量设置为1即可。如果您的应用程序是服务,则需要将OANOCACHE设置为系统环境变量(底层环境变量集)并重新启动。

答案 1 :(得分:0)

BSTR是两个数据元素。它是一个int,它具有基本字符串长度的计数,以及基本字符串。因此,即使您有BSTR {em}持有"",也必须在为其分配新的BSTR值之前正确清空它。否则,即使您释放“字符串”部分,也会泄漏int数据成员。

我怀疑你是否泄漏了fieldname.c_str()。它可能在堆栈上创建了一个BSTR并且正在泄漏。

改变您的代码来代替:

CComBSTR tempBSTR = fieldName.c_str();
hres = clsObj->Get ( tempBSTR, 0, &vVal, 0, 0 );

这至少可以让您确保在拨打Get()时,它不会自动构建BSTR

顺便说一下,如果您必须使用BSTR,请考虑在其位置使用CComBSTR。它可以帮助防止基本的内存泄漏。