6

泄漏检查器告诉我,在以下代码中分配的内存存在内存泄漏:

// 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 接口。

分配泄漏内存的特定行是“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 中。

4

2 回答 2

2

可能没有泄漏!请参阅Microsoft 的 Larry Osterman 关于该主题的这篇文章,其中描述了与您所看到的内容类似的内容:

我发现了一堆漏洞,并修复了它们,但是每次我们分配一个 BSTR 对象时,我都无法弄清楚的一个漏洞出现了。[...]

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

幸运的是,有一种方法可以禁用 BSTR 缓存,只需在启动应用程序之前将 OANOCACHE 环境变量设置为 1。如果您的应用程序是服务,那么您需要将 OANOCACHE 设置为系统环境变量(环境变量的底部集)并重新启动。
于 2013-01-10T05:32:53.753 回答
0

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

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

更改您的代码以执行此操作:

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

这至少可以让您确保它不是BSTR在您调用 Get() 时自动构建的泄漏。

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

于 2013-01-09T20:18:21.393 回答