wxFormBuilder / ticpp

This project is obsolete. TinyXML-2 offers a very similar C++ interface.
MIT License
92 stars 34 forks source link

memory leak ?? #43

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. see code below

What is the expected output? What do you see instead?
memory consumption increasing !! 

What version of the product are you using? On what operating system?
last one checkout done for here and also on 2.5.3

Please provide any additional information below.

(see valgrind output below)

[source lang="cpp"]
#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:
[source lang="cpp"]
<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>

[/source]

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)

Original issue reported on code.google.com by alainfa...@gmail.com on 25 Mar 2009 at 11:57

GoogleCodeExporter commented 9 years ago
One more details: it seem tinyxml allocate a new "wrapper" object every time it 
call
NextSiblingElement or FirstChildElement which is weird ! is this normal ? 

Original comment by alainfa...@gmail.com on 26 Mar 2009 at 8:21

GoogleCodeExporter commented 9 years ago
looking to the code of TiXml++ in ticpp.h/cpp
I found this:
a wrapper is created and added to (spawnedWrappers) each time a sibling is 
created
this vector will be bigger and bigger !

>> ticpp.cpp
Element* temp = new Element( sibling );
sibling->m_spawnedWrappers.push_back( temp );

is this normal ? no way to use only one wrapper or a map of wrapper ? to avoid 
memory
overflow in case of multiple access before closing the document.

Original comment by alainfa...@gmail.com on 26 Mar 2009 at 12:47

GoogleCodeExporter commented 9 years ago
Hi! Is this related with issue 42?

Original comment by sukend...@gmail.com on 24 Mar 2011 at 11:02

GoogleCodeExporter commented 9 years ago
Seem no update for this issue, I meet this problem now. before XML doc is 
closed, memory is keep raising. seems no way to free then dynamicly.

Original comment by go.aa.h...@gmail.com on 9 Nov 2011 at 2:27

GoogleCodeExporter commented 9 years ago
Hi,

Did anyone find a resolution to the memory leak issue? Please update the thread 
incase anyone has a solution.

Thanks

Original comment by shomadi...@gmail.com on 21 Oct 2013 at 10:17

GoogleCodeExporter commented 9 years ago
The workaround I found is to precharge the items I need from the xml at the 
begin of the program only once !! 
Regards
Alain

Original comment by alainfa...@gmail.com on 22 Oct 2013 at 11:20

GoogleCodeExporter commented 9 years ago
Hi Alain,

I am sorry, I did not get what you meant by precharge the items. Is there no 
code fix for this issue? It will be nice to have a small example of the 
workaround. Issue 61 also looks similar but there is no solution mentioned 
anywhere.

Thanks,
Adi

Original comment by shomadi...@gmail.com on 25 Oct 2013 at 9:27

GoogleCodeExporter commented 9 years ago
the leak is reported in the following manner:
/utilTinyXml.dll!ticpp::Document::Parse
/utilTinyXml.dll!TiXmlDocument::Parse
/utilTinyXml.dll!TiXmlElement::Parse
/utilTinyXml.dll!TiXmlElement::ReadValue
/utilTinyXml.dll!TiXmlElement::Parse
/utilTinyXml.dll!TiXmlElement::ReadValue
/utilTinyXml.dll!TiXmlElement::Parse
/utilTinyXml.dll!TiXmlElement::ReadValue
/utilTinyXml.dll!TiXmlElement::Parse
/utilTinyXml.dll!TiXmlElement::ReadValue
/utilTinyXml.dll!TiXmlElement::Parse
/utilTinyXml.dll!TiXmlElement::ReadValue
/utilTinyXml.dll!TiXmlElement::Parse
/utilTinyXml.dll!TiXmlElement::ReadValue
/msvcr100_clr0400.dll!operator new
/msvcr100_clr0400.dll!malloc
/ntdll.dll!RtlAllocateHeap
/ntdll.dll!RtlpLowFragHeapAllocFromContext
/ntdll.dll!RtlpAllocateUserBlock
/ntdll.dll!RtlAllocateHeap
/ntdll.dll!RtlpAllocateHeap
/ntdll.dll!RtlpExtendHeap
/ntdll.dll!RtlpFindAndCommitPages
/ntdll.dll!ZwAllocateVirtualMemory
/ntkrnlmp.exe!KiSystemServiceCopyEnd
/ntkrnlmp.exe! ?? ::NNGAKEGL::`string'

Original comment by shomadi...@gmail.com on 25 Oct 2013 at 9:35

GoogleCodeExporter commented 9 years ago
in my application, I have an xml that contains a certain number of parameters.
I preload those parameters ones upon initialization and store them into 
variables. 
I do not have to read them more then one.
Regards
Alain

Original comment by alainfa...@gmail.com on 25 Oct 2013 at 2:00

GoogleCodeExporter commented 9 years ago
See my comment(#7) to issue 42

Original comment by rldu...@gmail.com on 17 May 2014 at 10:42

GoogleCodeExporter commented 9 years ago
I don't believe this is at all related to issue 42. That seems to be a 
misunderstanding about how the reference counting works when using 
LinkEndChild().

This issue seems be caused by the method of how the wrappers generated and 
stored. Memory is still cleaned up when the document is destroyed. However, in 
an application where the document object has a long lifetime and is repeatedly 
accessed through functions such as FirstChildElement(), memory will 
continuously build up. I don't see a reason why FirstChildElement() needs to 
create a new wrapper each time it's called. All of them would be pointing to 
the same object. Instead of having a container such as:
std::vector< ticpp::Base* > m_spawnedWrappers
why not just have each TiXmlBase object (through it's base class TiCppRC) just 
contain a pointer to its own wrapper (created only when needed)? Maybe I am 
missing an obvious reason for this. Can someone explain the reason for a 
container? Thanks,
Ryan

Original comment by ryan.da...@gmail.com on 4 Feb 2015 at 3:43