Board index » cppbuilder » MSXML - resource-leak

MSXML - resource-leak


2005-01-12 09:47:54 PM
cppbuilder16
Hello.
I'm using MSXML (via TypeLib-import / COM-functionality) in my application.
Most of the MSXML-features are OK. But when I use
"IXMLDOMNode::get_nodeValue()" or "IXMLDOMNode::get_nodeTypedValue()" (which
are the member-functions for IXMLDOMNode::nodeValue / ::nodeTypedValue) on a
node with the type NODE_ATTRIBUTE, I will receive a resource-leak of exactly
16 Bytes each time! (I installed IMallocSpy for inspection purposes.)
For example:
IXMLDOMNodePtr
pXMLNode,
pXMLAttrNode;
IXMLDOMNamedNodeMapPtr
pXMLAttrList;
pXMLNode = pXMLDoc->selectSingleNode(L"//FIELDS/FIELD");
pXMLAttrList = pXMLNode->get_attributes();
pXMLAttrNode = pXMLAttrList->get_item(0);
Variant vBuff = pXMLAttrNode->get_nodeValue(); // =>resource-leak !!!
The question is: Is this an effect caused by the BCB TypeLib-import (wrong
wrapping-mechanism or kind like this) or is it caused by MSXML itself? Has
anyone experience with that or still better: a solution?
Thanks in advance,
Uli.
 
 

Re:MSXML - resource-leak

"Uli" < XXXX@XXXXX.COM >wrote in message
Quote
Hello.

I'm using MSXML (via TypeLib-import / COM-functionality) in my
application.
Most of the MSXML-features are OK. But when I use
"IXMLDOMNode::get_nodeValue()" or "IXMLDOMNode::get_nodeTypedValue()"
(which
are the member-functions for IXMLDOMNode::nodeValue / ::nodeTypedValue) on
a
node with the type NODE_ATTRIBUTE, I will receive a resource-leak of
exactly
16 Bytes each time! (I installed IMallocSpy for inspection purposes.)

For example:

IXMLDOMNodePtr
pXMLNode,
pXMLAttrNode;

IXMLDOMNamedNodeMapPtr
pXMLAttrList;

pXMLNode = pXMLDoc->selectSingleNode(L"//FIELDS/FIELD");
pXMLAttrList = pXMLNode->get_attributes();
pXMLAttrNode = pXMLAttrList->get_item(0);
Variant vBuff = pXMLAttrNode->get_nodeValue(); // =>resource-leak !!!

The question is: Is this an effect caused by the BCB TypeLib-import (wrong
wrapping-mechanism or kind like this) or is it caused by MSXML itself? Has
anyone experience with that or still better: a solution?

Thanks in advance,
Uli.

Post the code. It's very difficult to help with such little information. I
once had a memory leak using MSXML, but I found out that I forgot a release
and it was that obvious at first.
 

Re:MSXML - resource-leak

"Uli" < XXXX@XXXXX.COM >wrote in message
Quote
pXMLNode = pXMLDoc->selectSingleNode(L"//FIELDS/FIELD");
You should not specify COM strings like that. You are declaring a raw
wchar_t* string, but all COM strings use BSTR instead, which is not a raw
wchar_t* string. You need to either
1) call SysAllocString() and SysFreeString()
BSTR bstrField = SysAllocString(L"//FIELDS/FIELD");
pXMLNode = pXMLDoc->selectSingleNode(bstrField);
SysFreeString(bstrField);
2) use the WideString class:
pXMLNode = pXMLDoc->selectSingleNode(WideString("//FIELDS/FIELD"));
Quote
Variant vBuff = pXMLAttrNode->get_nodeValue(); // =>resource-leak !!!
get_nodeValue() returns a Win32 API VARIANT, not a VCL Variant. The VCL's
Variant class will make a copy of the VARIANT data. Thus the original
memory will never get freed. Change your declaration to the following
instead:
VARIANT vBuff = pXMLAttrNode->get_nodeValue();
If you must use a VCL Variant, then you have to free the VARIANT manually:
VARIANT v = pXMLAttrNode->get_nodeValue();
Variant vBuff = v;
::VariantClear(&v);
Quote
Is this an effect caused by the BCB TypeLib-import (wrong
wrapping-mechanism or kind like this) or is it caused by MSXML
itself?
Neither. The bug is in your own code that is misusing the VARIANT.
Gambit
 

{smallsort}

Re:MSXML - resource-leak

Quote
VARIANT v = pXMLAttrNode->get_nodeValue();
Variant vBuff = v;
::VariantClear(&v);

>Is this an effect caused by the BCB TypeLib-import (wrong
>wrapping-mechanism or kind like this) or is it caused by MSXML
>itself?
Doesn't TVariant store a reference?
 

Re:MSXML - resource-leak

"Mike King" < XXXX@XXXXX.COM >wrote in message
Quote
Doesn't TVariant store a reference?
Variant and TVariant both create a copy of the VARIANT, they do not store a
reference to it.
Gambit
 

Re:MSXML - resource-leak

Hello Remy/Gambit,
first thanks for answering. Sorry to contradict you, but (also when I didn't
post it) I tried the following alternatives:
Variant vBuff = pXMLAttrNode->get_nodeValue();
VARIANT vBuff = pXMLAttrNode->get_nodeValue();
tagVariant vBuff = pXMLAttrNode->get_nodeValue();
/* no return value */ pXMLAttrNode->get_nodeValue();
The effect (resource-leak) remains the same in each case!
For instance, if you use
Variant vBuff = pXMLAttrNode->get_nodeName();
there aren't any problems (it works fine exactly with THAT code!).
---
And additionally, as I said, the resource leak only occurs, when
pXMLAttrNode is of node-type NODE_ATTRIBUTE. If it is NODE_ELEMENT, no
resource-leak will be received. Caused by this I modified the code like
that:
IXMLDOMAttributePtr pXMLAttr = pXMLAttrNode;
... pXMLAttr->get_nodeValue();
but the leak still remains.
---
Furthermore I introduced several releases, e.g.
pXMLAttrNode.Release()
but: no chance
---
So, ... ???
Uli.
-------------------------------------
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >schrieb im Newsbeitrag
Quote

"Uli" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...

>pXMLNode = pXMLDoc->selectSingleNode(L"//FIELDS/FIELD");

You should not specify COM strings like that. You are declaring a raw
wchar_t* string, but all COM strings use BSTR instead, which is not a raw
wchar_t* string. You need to either

1) call SysAllocString() and SysFreeString()

BSTR bstrField = SysAllocString(L"//FIELDS/FIELD");
pXMLNode = pXMLDoc->selectSingleNode(bstrField);
SysFreeString(bstrField);

2) use the WideString class:

pXMLNode = pXMLDoc->selectSingleNode(WideString("//FIELDS/FIELD"));

>Variant vBuff = pXMLAttrNode->get_nodeValue(); // =>resource-leak
!!!

get_nodeValue() returns a Win32 API VARIANT, not a VCL Variant. The VCL's
Variant class will make a copy of the VARIANT data. Thus the original
memory will never get freed. Change your declaration to the following
instead:

VARIANT vBuff = pXMLAttrNode->get_nodeValue();

If you must use a VCL Variant, then you have to free the VARIANT manually:

VARIANT v = pXMLAttrNode->get_nodeValue();
Variant vBuff = v;
::VariantClear(&v);

>Is this an effect caused by the BCB TypeLib-import (wrong
>wrapping-mechanism or kind like this) or is it caused by MSXML
>itself?

Neither. The bug is in your own code that is misusing the VARIANT.


Gambit


 

Re:MSXML - resource-leak

Hello Mike,
my code is like that:
void __fastcall AnyFunction()
{
HRESULT hr;
DOMDocument40Ptr pXMLDoc;
IXMLDOMNodePtr pXMLNode,
pXMLAttrNode;
IXMLDOMAttributePtr pXMLAttr;
IXMLDOMNamedNodeMapPtr pXMLAttrList;
VARIANT_BOOL vbResult;
Variant vBuff; // several Variant types for experimental purposes
tagVARIANT tvBuff;
VARIANT VBuff;
hr = pXMLDoc.CreateInstance( L"Msxml2.DOMDocument.4.0");
if(FAILED(hr))
ErrorMsg(GetErrorMsg(hr));
hr = pXMLDoc->load( _V( L"country.xml" ) , &vbResult);
if(FAILED(hr))
ErrorMsg(GetErrorMsg(hr));
pXMLNode = pXMLDoc->selectSingleNode(WideString("//FIELDS/FIELD")); // I
modified it due to Remy's proposal
pXMLAttrList = pXMLNode->get_attributes();
pXMLAttrNode = pXMLAttrList->get_item(0);
vBuff = pXMLAttrNode->get_nodeValue();
pXMLNode.Release();
pXMLAttrList.Release();
pXMLAttrNode.Release();
pXMLDoc.Release();
}
---
The XML-document (which is only for experimental purposes) basically has the
form:
<?xml version = "1.0" standalone = "yes"?>
<DATAPACKET Version = "2.0">
<METADATA>
<FIELDS>
<FIELD attrname = "Name" fieldtype = "string" WIDTH = "24"/>
<FIELD attrname = "Capital" fieldtype = "string" WIDTH = "24"/>
<FIELD attrname = "Continent" fieldtype = "string" WIDTH = "24"/>
<FIELD attrname = "Area" fieldtype = "r8"/>
<FIELD attrname = "Population" fieldtype = "r8"/>
</FIELDS>
<PARAMS DEFAULT_ORDER = "1" PRIMARY_KEY = "1" LCID = "2057"/>
</METADATA>
<ROWDATA>
<ROW Name = "Argentina" Capital = "Buenos Aires" Continent = "South
America" Area = "2777815" Population = "32300003"/>
</ROWDATA>
</DATAPACKET>
---
Let me say that all the necessary releases are done automatically when the
sevaral interface-pointers leave the compound (here: the method). So
normally it is not necessary to implement an explicit release. Besides that,
the call of "pXMLAttrNode->Release();" in that case would be deadly, because
you free the memory which actually is done implicitely by leaving the
function.
Uli.
----------------
"Mike King" < XXXX@XXXXX.COM >schrieb im Newsbeitrag
Quote
"Uli" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...

Post the code. It's very difficult to help with such little information.
I
once had a memory leak using MSXML, but I found out that I forgot a
release
and it was that obvious at first.


 

Re:MSXML - resource-leak

"Uli" < XXXX@XXXXX.COM >wrote in message
Quote
Variant vBuff = pXMLAttrNode->get_nodeValue();
That wil leak for the reasons I already stated earlier.
Quote
VARIANT vBuff = pXMLAttrNode->get_nodeValue();
That will leak if you do not call VariantClean() when you are done with the
VARIANT.
Quote
tagVariant vBuff = pXMLAttrNode->get_nodeValue();
VARIANT is a typedef for tagVariant, so this is the same thing as the one
above.
Quote
/* no return value */ pXMLAttrNode->get_nodeValue();
That will definately leak since you are not managing the reurned VARIANT at
all.
Gambit
 

Re:MSXML - resource-leak

Damned! I think you were right - "::VariantClear(&v);" solves the problem!
Thanks at all,
Uli.
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >schrieb im Newsbeitrag
Quote

"Uli" < XXXX@XXXXX.COM >wrote in message
news:41e7908d$ XXXX@XXXXX.COM ...

>Variant vBuff = pXMLAttrNode->get_nodeValue();

That wil leak for the reasons I already stated earlier.

>VARIANT vBuff = pXMLAttrNode->get_nodeValue();

That will leak if you do not call VariantClean() when you are done with
the
VARIANT.

>tagVariant vBuff = pXMLAttrNode->get_nodeValue();

VARIANT is a typedef for tagVariant, so this is the same thing as the one
above.

>/* no return value */ pXMLAttrNode->get_nodeValue();

That will definately leak since you are not managing the reurned VARIANT
at
all.


Gambit