Solved

Question on Memory Management using MSXML4

Posted on 2003-11-05
9
1,011 Views
Last Modified: 2013-12-03
I have a question about when I am supposed to release pointers...

I am creating an xml document

MSXML2::IXMLDOMDocument *pDoc;
MSXML2::IXMLDOMElementPtr pNode;
MSXML2::IXMLDOMElementPtr pNode2
MSXML2::IXMLDOMElementPtr pNode3;

and constantly making calls like pNode = pDoc->createNode().

am I supposed to free some memory before I re-assign pNode?
0
Comment
Question by:jjacksn
  • 5
  • 4
9 Comments
 
LVL 12

Expert Comment

by:andrewjb
ID: 9685916
Yes. You need to call pNode->Release() when you've finished with it.

An easy way might be to use the CComPtr<> template wrapper, which does this for you as it acts as a smart pointer.

So, something like

CComPtr<IXMLDOMElement>  lNode;

lNode = SomeFunctionToGetYouANodeHere();

lNode = SomeOtherFunction();

and you get an automatic 'release' between the two.
0
 
LVL 5

Author Comment

by:jjacksn
ID: 9688805
thanks andrew, would the CComPt be transparent to my code?  
0
 
LVL 12

Accepted Solution

by:
andrewjb earned 150 total points
ID: 9688888
It's a standard wrapper defined in <atl\atlbase.h>

It's basically transparent, except for

a) If you put it into a container, you need to wrap the CComPtr in the CAdapt<> template

i.e.
NOT
vector< CComPtr<IUnknown> >  MyVec;
IUnknown *a;
CComPtr<IUnknown> b;
MyVec.push_back( a ); or push_back(b)

instead:

vector< CAdapt < CComPtr< IUnknown > > > MyVec
a & b as before
then push_back(a) or b is OK

and b) you can't use the & operator if the CComPtr is NOT NULL - because that would be silly, because you'd be changing the pointer without dealing with reference counts.


For something like a QueryInterface call, you'd do

CComPtr<IMyInterface> x;

something->QueryInterface( IID_IMyInterface, (void**) &x );
which is OK, but you MUST ensure that 'x' is NULL before the call.

The constructor initialises it to NULL, but you couldn't, for example, do:

something->QueryInterface( IID_IMyInterface, (void**) &x );
something->QueryInterface( IID_IMyInterface, (void**) &x );

in succession, without an explicit x = NULL between the two.

(the & operator in the second call will assert )


Andrew.


0
 
LVL 5

Author Comment

by:jjacksn
ID: 9689376
I'm have a problem.  I'm not trying to use CComPtrs, and just calling release.  However, I'm getting memory errors all over the place:  here is my strucutre:

MSXML2::IXMLDOMDocument *pDoc;
MSXML2::IXMLDOMElementPtr pRoot;
MSXML2::IXMLDOMElementPtr pTop1;
MSXML2::IXMLDOMElementPtr pTop2
MSXML2::IXMLDOMElementPtr pNode;
MSXML2::IXMLDOMElementPtr pNode2
MSXML2::IXMLDOMElementPtr pNode3;

pRoot = pDoc->getRoot();

while(info to be parserd)
{
pNode = pDoc->CreateNode()
pNode->SetAttribute() //a bunch of times
PNode2 = pDoc->CreateNode("to_be_child_of_pNode);
//Set attributes
pNode->appendChild(pNode2);
pNode2->Release()

if(somethinig)
pTop1->appendChild(pNode);
else
pTop2->appendChild(pNode);
pNode->Release()

}
pRoot->appendChild(pTop1);
pRoot->appendChild(pTop2);
pTop1->Release();
pTop2->Release();
pRoot->Release();
pDoc->release();

When I do the clenaup inside the loop, I get an error the second time through the loop.  If I don't free memory inside the loop, I get a memory error when the call returns and the caller tries to access and simple integer. When I don't make an Release calls, it completes with no errors (but I think I'm leaking memory).
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 12

Expert Comment

by:andrewjb
ID: 9689433
pRoot = pDoc->getRoot();   - This will AddRef on pRoot

while(info to be parserd)
{
pNode = pDoc->CreateNode()     - This will AddRef on pNode
pNode->SetAttribute() //a bunch of times  - this won't AddRef
PNode2 = pDoc->CreateNode("to_be_child_of_pNode); - This will AddRef on pNode2
//Set attributes
pNode->appendChild(pNode2);  -- This won't AddRef
pNode2->Release()  -- OK, so now pNode2 is clear. You shouldn't use it anymore.

if(somethinig)
pTop1->appendChild(pNode);  -- don't know where pTop1 and 2 are from?
else
pTop2->appendChild(pNode);
pNode->Release()  - ok, so you've release it, and shouldn't use it anymore

}
pRoot->appendChild(pTop1);  - no AddRef for you to worry about
pRoot->appendChild(pTop2);  - ditto
pTop1->Release(); - it depends where you got these from
pTop2->Release();
pRoot->Release(); - that looks right
pDoc->release();  - it depends where this comes from



So, in summary, that's probably right, though I don't know about pTop1 and 2

What error do you get, and on what line?

(And I'm about to go home now, so won't be back until tomorrow morning!)

0
 
LVL 5

Author Comment

by:jjacksn
ID: 9690643
Andrew,

pNode, pNode2, are going to be used loop goes through, aren't they just pointers?  I get an error in SetAttriute(), it says its null is that ok?  
0
 
LVL 12

Expert Comment

by:andrewjb
ID: 9693095
What does pNode equal after the CreateNode, then? Couldn't you just post a bit of code that's complete and does something, then I can compile it myself :-)
0
 
LVL 5

Author Comment

by:jjacksn
ID: 9697331
Adnrew, I just swtiched them all to CComPtrs, so hopefully that will take care of the problem.  I had a really weird bug however, and I was wondering if you may know the causse.

I was trying to extract first and last name from e-mail fields that were like "Firstname Lastname".  I had to account for middle names as well.  I forgot to examine the case when there was no space, so I was making calls like stl::string substring(0,-1) and they were just returning the entire string, I was then calling char* = string->c_str();  none of this ways giving erros, and all of the fields appeared valid in quickwatch, but I was getting a conversion error from the _bstr_t method that was being called inherently when passing char* args to node methods much later in the code.  

This code was running fine when the COM object was called from C++ code.  However, this was giving an error when run from C# code.  So, I very carefully made the exact same method calls between two test programs, and one returned fine, the C# code had an error.  Does the COM object have any idea what is calling it? (I thought not.)  If so, why?  If not, why would anything cause an error form one caller to another?
0
 
LVL 12

Expert Comment

by:andrewjb
ID: 9700160
No, it doesn't know who's calling it.

The obvious problem is a memory management one.

What's your compiler here? Borland? the c_str() function for strings in Borland is dangerous. It returns you a char* pointer that is only valid for as long as you don't change the original string at all, and it stays in scope.

So, something like

AnsiString AFunction(); {...}

char *MyStr = AFunction().c_str()

isn't really valid. The result of AFunction() is a temporary AnsiString. You then c_str() it, and get a char* which immedaitely becomes invalid 'cos the temporary goes out of scope.

You'd have to do

AnsiString lTempResult = AFunction()
char *MyStr = lTempResult.c_str()

// use MyStr now, before lTempResult goes out of scope.




Could that be related?
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now