Re: Memory problem in libxml++-2.6



2013-02-11 12:44, Jean Inderchit skrev:
Dear programmers,

I'm writing a program using libxml++2.6 version 2.34.1 on Ubuntu 12.10 64bit and according to valgrind there is a memory leak.
The program is simple:

#include <libxml++/libxml++.h>
#include <iostream>

int main(int argc, char* argv[])
{
    try
    {
        xmlpp::DomParser parser("example.xml");
    }
    catch(...)
    {
        std::cout << "Exception caught" << std::endl;
    }

    return 0;
}

==14723== HEAP SUMMARY:
==14723== in use at exit: 966 bytes in 20 blocks
==14723== total heap usage: 206 allocs, 186 frees, 50,191 bytes allocated
==14723==
==14723== Searching for pointers to 20 not-freed blocks
==14723== Checked 332,592 bytes
==14723==
==14723== 104 bytes in 1 blocks are still reachable in loss record 19 of 20
==14723== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14723== by 0x682BC1A: xmlNewRMutex (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.7.8)
==14723== by 0x687E194: ??? (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.7.8)
==14723== by 0x687E214: xmlDictCreate (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.7.8)
==14723== by 0x67B9774: xmlInitParserCtxt (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.7.8)
==14723== by 0x67B9BCB: xmlNewParserCtxt (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.7.8)
==14723== by 0x67CCB0D: xmlCreateURLParserCtxt (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.7.8)
==14723== by 0x510F32E: xmlpp::DomParser::parse_file(Glib::ustring const&) (in /usr/lib/libxml++-2.6.so.2.0.7)
==14723== by 0x510F9FD: xmlpp::DomParser::DomParser(Glib::ustring const&, bool) (in /usr/lib/libxml++-2.6.so.2.0.7)
==14723== by 0x4023E2: main (MNEntryPoint.cpp:200)
==14723==
==14723== LEAK SUMMARY:
==14723== definitely lost: 0 bytes in 0 blocks
==14723== indirectly lost: 0 bytes in 0 blocks
==14723== possibly lost: 0 bytes in 0 blocks
==14723== still reachable: 104 bytes in 1 blocks
==14723== suppressed: 862 bytes in 19 blocks
==14723==
==14723== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
==14723==
==14723== 1 errors in context 1 of 1:
==14723== Conditional jump or move depends on uninitialised value(s)
==14723== at 0x78564E0: inflateReset2 (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
==14723== by 0x78565D8: inflateInit2_ (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
==14723== by 0x7850323: ??? (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
==14723== by 0x67E38E5: ??? (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.7.8)
==14723== by 0x67E4011: __xmlParserInputBufferCreateFilename (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.7.8)
==14723== by 0x67B92B1: xmlNewInputFromFile (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.7.8)
==14723== by 0x67CCB35: xmlCreateURLParserCtxt (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.7.8)
==14723== by 0x510F32E: xmlpp::DomParser::parse_file(Glib::ustring const&) (in /usr/lib/libxml++-2.6.so.2.0.7)
==14723== by 0x510F9FD: xmlpp::DomParser::DomParser(Glib::ustring const&, bool) (in /usr/lib/libxml++-2.6.so.2.0.7)
==14723== by 0x4023E2: main (MNEntryPoint.cpp:200)
==14723== Uninitialised value was created by a heap allocation
==14723== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14723== by 0x78565B6: inflateInit2_ (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
==14723== by 0x7850323: ??? (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
==14723== by 0x67E38E5: ??? (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.7.8)
==14723== by 0x67E4011: __xmlParserInputBufferCreateFilename (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.7.8)
==14723== by 0x67B92B1: xmlNewInputFromFile (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.7.8)
==14723== by 0x67CCB35: xmlCreateURLParserCtxt (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.7.8)
==14723== by 0x510F32E: xmlpp::DomParser::parse_file(Glib::ustring const&) (in /usr/lib/libxml++-2.6.so.2.0.7)
==14723== by 0x510F9FD: xmlpp::DomParser::DomParser(Glib::ustring const&, bool) (in /usr/lib/libxml++-2.6.so.2.0.7)
==14723== by 0x4023E2: main (MNEntryPoint.cpp:200)

It comes from the method xmlpp::DomParser::parse_file(Glib::ustring const&), but this bug has apparently already been reported and patched years ago:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=469809

I'm pretty sure that the version on Quantal is the patched one without the bug, but I don't understand why I get this memory leak.


PS: I reported the bug on launchpad

--
Jean Inderchit


The amount of "still reachable" memory depends very much on which versions of libxml-++2.6  and libxml-2.0 you use.

I've made some tests on Ubuntu 12.04.

1. libxml-2.0 version 2.7.8, libxml++-2.6 version 2.34.1. This is what I get from the Synaptic package manager.

1.1 Your test program. Result from valgrind:
==3358== LEAK SUMMARY:
==3358==    definitely lost: 0 bytes in 0 blocks
==3358==    indirectly lost: 0 bytes in 0 blocks
==3358==      possibly lost: 0 bytes in 0 blocks
==3358==    still reachable: 554 bytes in 20 blocks
==3358==         suppressed: 0 bytes in 0 blocks

Most of the still reachable memory has been allocated from xmlpp::Document::Init::Init(). One block is similar to yours:
==3358== 84 bytes in 1 blocks are still reachable in loss record 19 of 20
==3358==    at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3358==    by 0x4421101: xmlNewRMutex (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==3358==    by 0x4475EDC: xmlInitializeDict (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==3358==    by 0x4475F88: xmlDictCreate (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==3358==    by 0x43AC044: xmlInitParserCtxt (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==3358==    by 0x43AC490: xmlNewParserCtxt (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==3358==    by 0x43BFCEA: xmlCreateURLParserCtxt (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==3358==    by 0x43BFDB6: xmlCreateFileParserCtxt (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==3358==    by 0x8048A5F: ??? (in /home/kjell/C_Cpp/libxmlplusplus-list/2013-02-12_memory_problem/example)

I don't know why valgrind could not produce a better call trace here.

1.2 Added xmlCleanupParser(); before return. Result:
==3339== HEAP SUMMARY:
==3339==     in use at exit: 0 bytes in 0 blocks
==3339==   total heap usage: 131 allocs, 131 frees, 40,183 bytes allocated
==3339==
==3339== All heap blocks were freed -- no leaks are possible

2. libxml-2.0 version 2.9.0, libxml++-2.6 version 2.36.0.

2.1 Your test program. Result from valgrind:
==3427== LEAK SUMMARY:
==3427==    definitely lost: 0 bytes in 0 blocks
==3427==    indirectly lost: 0 bytes in 0 blocks
==3427==      possibly lost: 4,476 bytes in 90 blocks
==3427==    still reachable: 20,258 bytes in 175 blocks
==3427==         suppressed: 0 bytes in 0 blocks

The still reachable memory that has been allocated from xmlpp::Document::Init::Init() is very similar to case 1.1, but not exactly equal. This version of libxml++ uses a Glib::Threads::Mutex. and therefore there is also a lot of still reachable and possibly lost memory that has been allocated by glib. But I can see none that has been allocated from xmlpp::DomParser.

2.2 Added xmlCleanupParser(); before return. Result:
==3461== LEAK SUMMARY:
==3461==    definitely lost: 0 bytes in 0 blocks
==3461==    indirectly lost: 0 bytes in 0 blocks
==3461==      possibly lost: 4,476 bytes in 90 blocks
==3461==    still reachable: 19,704 bytes in 155 blocks
==3461==         suppressed: 0 bytes in 0 blocks

All still reachable and possibly lost memory has been allocated from glib.

None of my results is exactly equal to yours. You could try to add xmlCleanupParser(); before return. You must also #include <libxml/parser.h>.

Is this really a problem, except that it's a nuisance when you want to search for dangerous memory leaks?
Have you tried to put the bulk of your main() function in a loop, to see if the amount of still reachable memory grows in proportion to the number of times the xmlpp::DomParser is created and deleted?

It's quite common, especially in programs that use glib's type system, to allocate memory blocks at the start of the program, use them now and then during the execution, and then rely on the operating system to free the memory when the program has exited. I would not consider that a memory leak, but it's a nuisance when you want to use valgrind to search for real memory leaks.

Kjell


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]