Reputation: 61
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.
Upvotes: 6
Views: 4392
Reputation: 14498
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.
Upvotes: 2
Reputation: 2272
A BSTR
is two data elements. It is an int
that has the count of the length of the basic string, and the basic string as well. So even if you have an emtpy BSTR
holding ""
, you have to empty it properly before assigning a new BSTR
value to it. Otherwise, even if you free the 'string' part, you leak away the int
data member.
I suspect you are leaking the fieldname.c_str(). It is probably creating a BSTR
on the stack and that is leaking away.
Alter your code to do this instead:
CComBSTR tempBSTR = fieldName.c_str();
hres = clsObj->Get ( tempBSTR, 0, &vVal, 0, 0 );
This will at a minimum let you make sure it isn't an auto built BSTR
leaking away on your call to Get().
By the way, if you have to work with BSTR
, look into using CComBSTR
in its place. It can help prevent basic memory leaks.
Upvotes: 0