Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I solve memory leaks that are reported to reside in STL string?

For a school project, we have to send big files across the network., we must use Poco::XML for our data.

After our files are send over the network, it appears that the memory does not free.

Here is an example for a file of ~9 Mb on the receiving part:

valgrind --leak-check=full --show-reachable=yes -v ourExecutable parms returns:

 12,880,736 bytes in 37 blocks are definitely lost in loss record 101 of 101
    at 0x4C2747E: operator new(unsigned long) (vg_replace_malloc.c:261)
    by 0x5A3AC88: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/libstdc++.so.6.0.13)
    by 0x5A3BC4A: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/libstdc++.so.6.0.13)
    by 0x5A3C1BB: std::string::reserve(unsigned long) (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/libstdc++.so.6.0.13)
    by 0x5A3C68E: std::string::append(std::string const&) (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/libstdc++.so.6.0.13)
    by 0x5202359: Poco::XML::Element::innerText() const (in /home/tomwij/IGS/trunk/Project/external/lib/libPocoXML.so.8)
    by 0x4145BF: NodeProtocol::getChildNodeStrValue(Poco::XML::Element*, std::string) (NodeProtocol.cpp:82)
    by 0x41544F: NodeProtocol::deserialize(std::string const&) (NodeProtocol.cpp:200)
    by 0x40B088: Node::handleClientPacket(PriorityElement*) (Node.cpp:760)
    by 0x40A04C: Node::handlePackets() (Node.cpp:574)
    by 0x4078EA: Node::run() (Node.cpp:162)
    by 0x40772D: Node::activate() (Node.cpp:138)

 LEAK SUMMARY:
    definitely lost: 12,888,036 bytes in 190 blocks
    indirectly lost: 644,979 bytes in 1,355 blocks
      possibly lost: 10,089 bytes in 27 blocks
    still reachable: 306,020 bytes in 43 blocks
         suppressed: 0 bytes in 0 blocks

The function which is right before Poco is

const string NodeProtocol::getChildNodeStrValue(Element * elem, string child)
{
    Element*  tempNode = elem->getChildElement(child);
    XMLString result(tempNode->innerText());
    string ret = string(fromXMLString(result));
    result.clear();
    return ret;
}

which calls

XMLString Element::innerText() const
{
    XMLString result;
    Node* pChild = firstChild();
    while (pChild)
    {
        result.append(pChild->innerText());
        pChild = pChild->nextSibling();
    }
    return result;
}

(Note that XMLString is std::string)

Why is the append of STL string leaking memory?

If I just assign instead of using the copy constructors it gives the same problem.


EDIT:

I'm using the latest stable GNU GCC 4.4.4 on Gentoo x64 (linux-2.6.34-gentoo-r12).

More functions from the call stack (stripped irrelevant big chunks of code / if structures):

Command * NodeProtocol::deserialize(const string & msg)
{
    DOMParser xmlParser;

    // Get the root node.
    AutoPtr<Document> doc = xmlParser.parseString(msg);
    AutoPtr<Element> rootElement = doc->documentElement();

    string root = fromXMLString(rootElement->nodeName());
    string name = getChildNodeStrValue(rootElement, "name");
    string data = getChildNodeStrValue(rootElement, "data");
    return new PutCommand(name, data);
}

and

void Node::handleClientPacket(PriorityElement * prio)
{
        Command * command = NodeProtocol::deserialize(prio->fPacket);

        // CUT: Access some properties of command, let the command execute.

        delete command;
}

and

void Node::handlePackets()
{
    PriorityElement * prio = fQueue->top();
    fQueue->pop();

    if (prio->fSource == kCLIENT)
        handleClientPacket(prio);
    else if (prio->fSource == kNODE)
        handleNodePacket(prio);

    delete prio;
}

where fQueue is:

priority_queue< PriorityElement*,  vector<PriorityElement*>, ComparisonFunction >
like image 368
Tamara Wijsman Avatar asked Jul 10 '11 21:07

Tamara Wijsman


People also ask

How do you handle memory leaks?

To avoid memory leaks, memory allocated on heap should always be freed when no longer needed.

How do you handle memory leaks in C++?

The best way to avoid memory leaks in C++ is to have as few new/delete calls at the program level as possible – ideally NONE. Anything that requires dynamic memory should be buried inside an RAII object that releases the memory when it goes out of scope.

How do I find a memory leak in C++?

The primary tools for detecting memory leaks are the C/C++ debugger and the C Run-time Library (CRT) debug heap functions. The #define statement maps a base version of the CRT heap functions to the corresponding debug version. If you leave out the #define statement, the memory leak dump will be less detailed.

What causes memory leaks C++?

Memory leaks occur when new memory is allocated dynamically and never deallocated. In C programs, new memory is allocated by the malloc or calloc functions, and deallocated by the free function.

How to avoid memory leaks in C++?

1 Instead of managing memory manually, try to use smart pointers where applicable. 2 use std::string instead of char *. ... 3 Never use a raw pointer unless it’s to interface with an older lib. 4 The best way to avoid memory leaks in C++ is to have as few new/delete calls at the program level as possible – ideally NONE. ... More items...

What is memory leakage?

Memory leaks are a problem every developer has to face eventually. Even when working with memory-managed languages there are cases where memory can be leaked. Leaks are the cause of whole class of problems: slowdowns, crashes, high latency, and even problems with other applications.

Is there a permanent solution to a memory leak?

The permanent solution of course is to get software updates for any applications or drivers that happen to have a memory leak, fixing the problem. In an ideal world, leaks wouldn't happen, but with software becoming increasingly complex, sometimes things are missed.

How to leak memory from a web page?

Open the example in Chrome, open the Dev Tools, go to timeline, select memory and click the record button. Then go to the page and click The Button to start leaking memory. After a while stop the recording and take a look at the results:


1 Answers

I would make this a comment, but apparently I don't have the rep. Have you remembered to make the destructor for Command virtual? If name or data are fields of PutCommand rather than Command and the Command destructor is not virtual, they may not be freed properly when you delete command in handleClientPacket.

like image 144
Hugh Avatar answered Oct 15 '22 18:10

Hugh