泄漏检查程序告诉我内存中存在内存泄漏,该代码在以下代码中分配:
// 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中。
答案 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
。它可以帮助防止基本的内存泄漏。