Solved

Question on Memory Management using MSXML4

Posted on 2003-11-05
9
1,013 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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

912 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

26 Experts available now in Live!

Get 1:1 Help Now