2

I am using Valgrind (a memory leak tool) to find a potential memory leak. It was run as such:

$ valgrind --leak-check=full ./myApp

The following was reported:

==9458== 15,007 bytes in 126 blocks are possibly lost in loss record 622 of 622
==9458==    at 0x4029FDE: operator new(unsigned int) (vg_replace_malloc.c:313)
==9458==    by 0x415F213: std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.19)
==9458==    by 0x4161125: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.19)
==9458==    by 0x41617AF: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.19)
==9458==    by 0x808B061: Parser::parseLinear(rapidxml::xml_node<char>*, Linear*) (Parser.cpp:663)

==9458== 
==9458== LEAK SUMMARY:
==9458==    definitely lost: 0 bytes in 0 blocks
==9458==    indirectly lost: 0 bytes in 0 blocks
==9458==      possibly lost: 20,747 bytes in 257 blocks
==9458==    still reachable: 57,052 bytes in 3,203 blocks
==9458==         suppressed: 0 bytes in 0 blocks
==9458== Reachable blocks (those to which a pointer was found) are not shown.
==9458== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==9458== 
==9458== For counts of detected and suppressed errors, rerun with: -v
==9458== ERROR SUMMARY: 21 errors from 21 contexts (suppressed: 0 from 0)

It looks like there is a "possibly lost" memory leak based on the summary. However, after tracking down line 663 in Parser.cpp, I can't seem to identify the issue. xml_node<>* is part of the open source library RapidXML. The source code looks like this:

line 661: Tracker track;
line 662: xml_node<>* trackingNode = node->first_node(); // rapidxml API
line 663: track.setValue(trackingNode->first_node()->value());

Where setValue is defined as:

void Tracker::setValue(const string& s) {
    this->val = s;
}
code
  • 5,294
  • 16
  • 62
  • 113
  • Is `setValue()` inlined? Is `val` a `string`? – jxh Sep 03 '14 at 19:21
  • Hi jxh, yes val is a string. setValue is actually a member function of a class. It should look like: void myClass::setValue(const string& s) – code Sep 03 '14 at 19:23
  • Is the `setValue()` method defined in the header file of the class, or explicitly declared `inline`, or defined in a place where the its source body has already been parsed by the compiler when line 663 is being compiled? I want to know if the function call got inlined. – jxh Sep 03 '14 at 19:29
  • Also, xml_node<>* is part of an open source library called RapidXML. The first_node() api is documented here: http://rapidxml.sourceforge.net/manual.html#classrapidxml_1_1xml__node_7823e36687669e59c2afdf66334ef35a_17823e36687669e59c2afdf66334ef35a – code Sep 03 '14 at 19:30
  • @jxh, setValue() method is defined in a .cpp file outside of the header file of the class and not declared as inline – code Sep 03 '14 at 19:31
  • But is it also defined in Parser.cpp? – jxh Sep 03 '14 at 19:38
  • @jxh, sorry - I updated the code in the original post. setValue is a member function of a class named Tracker. The setValue() function is declared in Tracker.h and defined in Tracker.cpp. Parser.cpp includes "Tracker.h" at the top of the file – code Sep 03 '14 at 19:49
  • It's really weird because, I confirmed that I was able to print the value of the string, meaning that it exists. – code Sep 03 '14 at 19:58
  • Should I not declare/define the parameter as "const string&"? – code Sep 03 '14 at 19:58
  • Is there a problem with the shared library: /usr/lib/i386-linux-gnu/libstdc++.so.6.0.19 or vg_replace_malloc.c:313 ??? – code Sep 03 '14 at 19:59
  • It might be that the trouble is that there's a circular list (or other data structure) of nodes, each with a link to enough others that no single node is completely lost, yet there isn't a way to access any of the nodes from the rest of the program. In terms of the visible code, maybe the value in `node` (`node->first_node()`) has been set to null but the data structure it pointed at hasn't been cleaned up properly (if at all). – Jonathan Leffler Sep 03 '14 at 20:58
  • Possibly of interest: http://stackoverflow.com/questions/3537713/valgrind-can-possibly-lost-be-treated-as-definitely-lost – Jeremy Friesner Sep 03 '14 at 22:50

1 Answers1

1

According to the rapidxml manual, xml_base::value() doesn't return zero-terminated string with the rapidxml::parse_no_string_terminators option.

Terminate your string according to xml_base::value_size() if this option was set.

Also, before calling xml_base::value() check if the value is not empty. In other case value() returns empty string that can be another memory leak issue.

ralv
  • 46
  • 5