Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ leak with VARIANT / bstrVal code

A leak checker tells me that I have a memory leak on memory that is allocated in the following code:

// 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 );

The "clsObj" in there is a IWbemClassObject, which is a Microsoft interface for WMI stuff.

The specific line that allocates the leaked memory is the "clsObj->Get" line. The leak checker then reports more specific code for the leak itself (i.e. further in the stack trace at the time of the allocation of the leaked memory) for which I don't have the source code:

(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  

So the underlying BSTR in the VARIANT vVal is being leaked, it seems. But I'm doing a VariantClear... do I have to do something else?

Perhaps I'm leaking it in the wstring constructor? But if so, I don't understand. I thought bstrVal essentially just boils down to a char pointer (or wchar or whatever); the wstring constructor should just copy from that address as if it were any other pointer, right?

It's not like the wstring constructor takes over responsibility for clearing up the memory that's originally pointed to by vVal.bstrVal, as if it were doing a Detach() on some reference counted COM object, is it?

In case it matters, this is in Visual C++ 6.

like image 976
user1964027 Avatar asked Jan 09 '13 19:01

user1964027


1 Answers

There may be no leak! See this article by Microsoft's Larry Osterman on the subject which describes something similar to what you are seeing:

I found a bunch of the leaks, and fixed them, but one of the leaks I just couldn't figure out showed up every time we allocated a BSTR object. [...]

Basically, OLE caches all BSTR objects allocated in a process to allow it to pool together strings. As a result, these strings are effectively leaked "on purpose". [...]

Fortunately, there's a way of disabling the BSTR caching, simply set the OANOCACHE environment variable to 1 before launching your application. If your application is a service, then you need to set OANOCACHE as a system environment variable (the bottom set of environment variables) and reboot.
like image 78
BrendanMcK Avatar answered Oct 16 '22 00:10

BrendanMcK