TinyXML++ memory leaks

Started by
19 comments, last by Codeka 15 years ago
Hi I have huge memory leak issue using tinyxml with this code : any idea please ?

ticpp::Document   xml;
ticpp::Node     * _top;

filename="myfile";


xml.LoadFile(filename);
_top = xml.FirstChild(false);

ticpp::Element * _atomsib (std::string name) {
	for (ticpp::Element* pElem = _top->FirstChildElement(); pElem; ) {
		if (pElem->Value() == name) {
			return pElem;
		}
		ticpp::Element * tmp = pElem;
		pElem= pElem->NextSiblingElement("atom");
		tmp->Clear();
		delete tmp;
	};
	return 0;
}

while (1) {
	ticpp::Element * n;
	n = _atomsib("socket");
	n->Clear();
	delete n;
};





[Edited by - leelouch on March 24, 2009 7:18:32 PM]
Advertisement
delete pElem;
...
pElem = (ticpp::Element*) pElem->NextSiblingElement("atom")

I see a problem. And it isn't a memory leak.
I dont know about the above code, but tinyxml did used to leak years ago,
do u have the latest version?
Quote:Original post by NotAYakk
delete pElem;
...
pElem = (ticpp::Element*) pElem->NextSiblingElement("atom")

I see a problem. And it isn't a memory leak.


Yes of course, this is a problem, I figured out that, and even with the fix, it does not change the behaviour !!
maybe I missed something on what I have to do to free the memory allocated by the iterator, other than the Clear() method and delete on Element * ???

and Yes I have the last version .

What is the correct code to search an element in a xml hierarchy, without memory leak ??

Thanks for help.
You don't have to do anything to free memory. When the XML document itself is unloaded, all elements are freed as well.
Quote:Original post by Codeka
You don't have to do anything to free memory. When the XML document itself is unloaded, all elements are freed as well.


What if I do not want to unload the XML document ? (take it as a database)
in this case, the while loop above will increase the memory till saturation (is this normal ?).

valgrind mention that blocks allocated by tinyxml are still reachable.

anyway to avoid that ?
Quote:Original post by leelouch
What if I do not want to unload the XML document ? (take it as a database)
in this case, the while loop above will increase the memory till saturation (is this normal ?).
No, tinyxml allocates memory for the whole document up-front. As you enumerate elements, it just returns its internal pointers. So the same element will return the same pointer each time.
Quote:Original post by Codeka
Quote:Original post by leelouch
What if I do not want to unload the XML document ? (take it as a database)
in this case, the while loop above will increase the memory till saturation (is this normal ?).
No, tinyxml allocates memory for the whole document up-front. As you enumerate elements, it just returns its internal pointers. So the same element will return the same pointer each time.


Ok this is good to know, so normaly if I remove my delete and clear, memory must not increase, but this it'is not the case ! ->
pointer change !

very simple example : you can try it :)
pElem change ->
0x8d7dfd8
0x8d7dfe8
0x8d7dff8
0x8d7e008
0x8d7e018
0x8d7e028
0x8d7e038
0x8d7e048

(see also valgrind output below)

#include <ticpp.h>#include <ostream>using namespace std;int main() {	ticpp::Document   xml;	string topName;	ticpp::Node * _top;	xml.LoadFile("test.xml");	_top    = xml.FirstChild(false); // throwIfNoChildren=false	topName = ((ticpp::Element*)_top)->GetAttribute("atom");	cout << topName << endl;		while (1) {		ticpp::Element * pElem = _top->FirstChildElement();		cout << pElem << endl;	};}



test.xml:
<params atom="unit_2ddfba91" name="top">        <atom name="base_22475976">                <step value="0">                        <param name="enRead" type="Boolean" value="True"/>                        <param name="enWrite" type="Boolean" value="True"/>                </step>        </atom>        <atom name="base_22111976">                <step value="0">                        <param name="enRead" type="Boolean" value="False"/>                        <param name="enWrite" type="Boolean" value="True"/>                </step>        </atom></params>


valgrind output:
valgrind --log-file=val --leak-resolution=high --leak-check=full --show-reachable=yes test.out

==28684== 624 bytes in 12 blocks are still reachable in loss record 38 of 40==28684==    at 0x4004790: operator new(unsigned) (vg_replace_malloc.c:164)==28684==    by 0x80665A5: TiXmlElement::Parse(char const*, TiXmlParsingData*, TiXmlEncoding) (in test.out)==28684==    by 0x806623D: TiXmlElement::ReadValue(char const*, TiXmlParsingData*, TiXmlEncoding) (in test.out)==28684==    by 0x806670D: TiXmlElement::Parse(char const*, TiXmlParsingData*, TiXmlEncoding) (in test.out)==28684==    by 0x806623D: TiXmlElement::ReadValue(char const*, TiXmlParsingData*, TiXmlEncoding) (in test.out)==28684==    by 0x806670D: TiXmlElement::Parse(char const*, TiXmlParsingData*, TiXmlEncoding) (in test.out)==28684==    by 0x806623D: TiXmlElement::ReadValue(char const*, TiXmlParsingData*, TiXmlEncoding) (in test.out)==28684==    by 0x806670D: TiXmlElement::Parse(char const*, TiXmlParsingData*, TiXmlEncoding) (in test.out)==28684==    by 0x8066B6A: TiXmlDocument::Parse(char const*, TiXmlParsingData*, TiXmlEncoding) (in test.out)==28684==    by 0x8063333: TiXmlDocument::LoadFile(_IO_FILE*, TiXmlEncoding) (in test.out)==28684==    by 0x80634E9: TiXmlDocument::LoadFile(char const*, TiXmlEncoding) (in test.out)==28684==    by 0x804DFB4: ticpp::Document::LoadFile(char const*, TiXmlEncoding) (in test.out)==28684====28684====28684== 8,388,608 bytes in 1 blocks are still reachable in loss record 39 of 40==28684==    at 0x4004790: operator new(unsigned) (vg_replace_malloc.c:164)==28684==    by 0x805C5BB: std::vector<ticpp::Base*, std::allocator<ticpp::Base*> >::_M_insert_aux(__gnu_cxx::__normal_iterator<ticpp::Base**, std::vector<ticpp::Base*, std::allocator<ticpp::Base*> > >, ticpp::Base* const&) (in test.out)==28684==    by 0x8054304: ticpp::Node::FirstChildElement(char const*, bool) const (in test.out)==28684==    by 0x805443E: ticpp::Node::FirstChildElement(bool) const (in test.out)==28684==    by 0x804AD95: main (params.cc:97)==28684====28684====28684== 12,748,332 bytes in 1,062,361 blocks are still reachable in loss record 40 of 40==28684==    at 0x4004790: operator new(unsigned) (vg_replace_malloc.c:164)==28684==    by 0x8053EC5: ticpp::Node::FirstChildElement(char const*, bool) const (in test.out)==28684==    by 0x805443E: ticpp::Node::FirstChildElement(bool) const (in test.out)==28684==    by 0x804AD95: main (params.cc:97)

Quote:Original post by leelouch
#include <ticpp.h>#include <ostream>using namespace std;int main() {	ticpp::Document   xml;	string topName;	ticpp::Node * _top;	xml.LoadFile("test.xml");	_top    = xml.FirstChild(false); // throwIfNoChildren=false	topName = ((ticpp::Element*)_top)->GetAttribute("atom");	cout << topName << endl;		while (1) {		ticpp::Element * pElem = _top->FirstChildElement();		cout << pElem << endl;	};}



How are you stopping your program if you have an infinite loop at the end? Try just running that last loop a couple of hundred times and let the program terminate itself.
Otherwise, ticpp::Document xml won't go out of scope and be destroyed. You're probably just seeing memory that was allocated by the Document-object, but its destructor isn't called when your terminate the program with Ctrl-C.
That's my guess anyway.
Quote:Original post by Tunah


How are you stopping your program if you have an infinite loop at the end? Try just running that last loop a couple of hundred times and let the program terminate itself.
Otherwise, ticpp::Document xml won't go out of scope and be destroyed. You're probably just seeing memory that was allocated by the Document-object, but its destructor isn't called when your terminate the program with Ctrl-C.
That's my guess anyway.


This is just an example !
Let's say that xml is a global variable and I do not want to destroy it and reload it again on each time I need an attribute or something else.
The while statement here is only to simulate several access to the xml document ! Access to xml database must not reallocate a new element on each time you access to it. it must have like a cache on element already allocated and return cached pointer.

the while loop must not create an infinite allocation behavior. memory allocation size must remains constant during the loop where here is not the case !

This topic is closed to new replies.

Advertisement