1

On a Linux machine, run this script to compile a small C++ application and run it under valgrind:

#!/bin/bash

set -x -e

cd /tmp

cat > main.cpp <<EOF
#include <stdlib.h> // exit()
#include <string>   // std::string
int main(int argc, char *argv[], char *const envp[])
{
  std::string the_temp_string("bla bla bla"); 
  exit(0);
  return 0;
} // end main
EOF

lsb_release -d
/usr/bin/g++ --version

/usr/bin/g++  -MD -DDEBUG -g -ggdb -gstabs+ -O0  -fPIC  -Wall -Werror -Wsynth -Wno-comment -Wreturn-type   main.cpp -c -o main.o
/usr/bin/g++  -MD -DDEBUG -g -ggdb -gstabs+ -O0  -fPIC  -Wall -Werror -Wsynth -Wno-comment -Wreturn-type   main.o -L. -L/usr/lib64 -lstdc++  -o main.exe   

rm -f valgrind.xml
/usr/bin/valgrind \
  --xml=yes \
  --xml-file=valgrind.xml \
  --demangle=yes \
  --gen-suppressions=all \
  --track-origins=yes \
  --leak-check=full \
  --show-reachable=no \
  --num-callers=40 \
  ./main.exe \
  && cat valgrind.xml

The output of the above for my RHEL 6.8 machine gives:

+ cd /tmp
+ cat
+ lsb_release -d
Description:    Red Hat Enterprise Linux Workstation release 6.8 (Santiago)
+ /usr/bin/g++ --version
g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-17)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

+ /usr/bin/g++ -MD -DDEBUG -g -ggdb -gstabs+ -O0 -fPIC -Wall -Werror -Wsynth -Wno-comment -Wreturn-type main.cpp -c -o main.o
+ /usr/bin/g++ -MD -DDEBUG -g -ggdb -gstabs+ -O0 -fPIC -Wall -Werror -Wsynth -Wno-comment -Wreturn-type main.o -L. -L/usr/lib64 -lstdc++ -o main.exe
+ rm -f valgrind.xml
+ /usr/bin/valgrind --xml=yes --xml-file=valgrind.xml --demangle=yes --gen-suppressions=all --track-origins=yes --leak-check=full --show-reachable=no --num-callers=40 ./main.exe
+ cat valgrind.xml
<?xml version="1.0"?>

<valgrindoutput>

<protocolversion>4</protocolversion>
<protocoltool>memcheck</protocoltool>

<preamble>
  <line>Memcheck, a memory error detector</line>
  <line>Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.</line>
  <line>Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info</line>
  <line>Command: ./main.exe</line>
</preamble>

<pid>23040</pid>
<ppid>23010</ppid>
<tool>memcheck</tool>

<args>
  <vargv>
    <exe>/usr/bin/valgrind</exe>
    <arg>--xml=yes</arg>
    <arg>--xml-file=valgrind.xml</arg>
    <arg>--demangle=yes</arg>
    <arg>--gen-suppressions=all</arg>
    <arg>--track-origins=yes</arg>
    <arg>--leak-check=full</arg>
    <arg>--show-reachable=no</arg>
    <arg>--num-callers=40</arg>
  </vargv>
  <argv>
    <exe>./main.exe</exe>
  </argv>
</args>

<status>
  <state>RUNNING</state>
  <time>00:00:00:00.051 </time>
</status>


<status>
  <state>FINISHED</state>
  <time>00:00:00:00.298 </time>
</status>

<error>
  <unique>0x6</unique>
  <tid>1</tid>
  <kind>Leak_PossiblyLost</kind>
  <xwhat>
    <text>36 bytes in 1 blocks are possibly lost in loss record 1 of 1</text>
    <leakedbytes>36</leakedbytes>
    <leakedblocks>1</leakedblocks>
  </xwhat>
  <stack>
    <frame>
      <ip>0x4A075FC</ip>
      <obj>/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so</obj>
      <fn>operator new(unsigned long)</fn>
      <dir>/builddir/build/BUILD/valgrind-3.8.1/coregrind/m_replacemalloc</dir>
      <file>vg_replace_malloc.c</file>
      <line>298</line>
    </frame>
    <frame>
      <ip>0x3138C9C3C8</ip>
      <obj>/usr/lib64/libstdc++.so.6.0.13</obj>
      <fn>std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator&lt;char&gt; const&amp;)</fn>
    </frame>
    <frame>
      <ip>0x3138C9CDE4</ip>
      <obj>/usr/lib64/libstdc++.so.6.0.13</obj>
    </frame>
    <frame>
      <ip>0x3138C9CF32</ip>
      <obj>/usr/lib64/libstdc++.so.6.0.13</obj>
      <fn>std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;::basic_string(char const*, std::allocator&lt;char&gt; const&amp;)</fn>
    </frame>
    <frame>
      <ip>0x40075C</ip>
      <obj>/tmp/main.exe</obj>
      <fn>main</fn>
    </frame>
  </stack>
  <suppression>
    <sname>insert_a_suppression_name_here</sname>
    <skind>Memcheck:Leak</skind>
    <sframe> <fun>_Znwm</fun> </sframe>
    <sframe> <fun>_ZNSs4_Rep9_S_createEmmRKSaIcE</fun> </sframe>
    <sframe> <obj>/usr/lib64/libstdc++.so.6.0.13</obj> </sframe>
    <sframe> <fun>_ZNSsC1EPKcRKSaIcE</fun> </sframe>
    <sframe> <fun>main</fun> </sframe>
    <rawtext>
<![CDATA[
{
   <insert_a_suppression_name_here>
   Memcheck:Leak
   fun:_Znwm
   fun:_ZNSs4_Rep9_S_createEmmRKSaIcE
   obj:/usr/lib64/libstdc++.so.6.0.13
   fun:_ZNSsC1EPKcRKSaIcE
   fun:main
}
]]>
    </rawtext>
  </suppression>
</error>

<errorcounts>
</errorcounts>

<suppcounts>
  <pair>
    <count>4</count>
    <name>U1004-ARM-_dl_relocate_object</name>
  </pair>
  <pair>
    <count>2</count>
    <name>glibc-2.5.x-on-SUSE-10.2-(PPC)-2a</name>
  </pair>
</suppcounts>

</valgrindoutput>

Applying the GLIBCXX_FORCE_NEW variable as indicated in the https://stackoverflow.com/a/7284726/257924 answer had no effect.

So my question is this: Is this a bug in valgrind, in the C++ standard library version on this machine, or my own misunderstanding of how the C++ library gets torn down at/near ::exit() call time?

My current thinking is that I can should just suppress it in valgrind and move on.

2
  • Note: Commenting out the call to exit(0) causes the valgrind error to disappear. Commented Aug 25, 2017 at 2:11
  • 1
    Yes, when you comment out the exit, then main returns, and the destructor of the std::string is called, and releases the memory. Note that the newer versions of valgrind better understand the reachability of std::string (see my answer below) Commented Aug 25, 2017 at 13:27

2 Answers 2

2

You are using a very old valgrind release (3.8.1), and so you do not benefit from the new improved features. Some valgrind releases ago, some c++ related heuristics were added to Valgrind, so as a.o. to better understand std::string.

Note that xml output contains less information than the textual output (e.g. does not give details about used heuristics).

The last version of valgrind gives the below output, showing that the std::string has been recognised using the stdstring heuristic. See more details about heuristics at http://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.leaks

==10282== Memcheck, a memory error detector
==10282== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10282== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==10282== Command: ./g
==10282== 
==10282== 
==10282== HEAP SUMMARY:
==10282==     in use at exit: 36 bytes in 1 blocks
==10282==   total heap usage: 1 allocs, 0 frees, 36 bytes allocated
==10282== 
==10282== LEAK SUMMARY:
==10282==    definitely lost: 0 bytes in 0 blocks
==10282==    indirectly lost: 0 bytes in 0 blocks
==10282==      possibly lost: 0 bytes in 0 blocks
==10282==    still reachable: 36 bytes in 1 blocks
==10282==                       of which reachable via heuristic:
==10282==                         stdstring          : 36 bytes in 1 blocks
==10282==         suppressed: 0 bytes in 0 blocks
==10282== Rerun with --leak-check=full to see details of leaked memory
==10282== 
==10282== For counts of detected and suppressed errors, rerun with: -v
==10282== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Sign up to request clarification or add additional context in comments.

2 Comments

If I had the option to upgrade to a newer RHEL OS, and along with it the gcc compiler toolchain, I could alleviate this. Without that, I'll just ignore it with a valgrind suppression. Thank you!
Note that it is quite easy to compile and install your own version of valgrind. But without that, effectively, a suppression entry is the way to go.
0

Must be a bug in the standard C++ library or something else beyond my immediate control, as I retried the script on my Ubuntu box and got:

+ cd /tmp
+ cat
+ lsb_release -d
Description:    Ubuntu 17.04
+ /usr/bin/g++ --version
g++ (Ubuntu 6.3.0-12ubuntu2) 6.3.0 20170406
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

+ /usr/bin/g++ -MD -DDEBUG -g -ggdb -gstabs+ -O0 -fPIC -Wall -Werror -Wsynth -Wno-comment -Wreturn-type main.cpp -c -o main.o
+ /usr/bin/g++ -MD -DDEBUG -g -ggdb -gstabs+ -O0 -fPIC -Wall -Werror -Wsynth -Wno-comment -Wreturn-type main.o -L. -L/usr/lib64 -lstdc++ -o main.exe
+ rm -f valgrind.xml
+ /usr/bin/valgrind --xml=yes --xml-file=valgrind.xml --demangle=yes --gen-suppressions=all --track-origins=yes --leak-check=full --show-reachable=no --num-callers=40 ./main.exe
+ cat valgrind.xml
<?xml version="1.0"?>

<valgrindoutput>

<protocolversion>4</protocolversion>
<protocoltool>memcheck</protocoltool>

<preamble>
  <line>Memcheck, a memory error detector</line>
  <line>Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.</line>
  <line>Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info</line>
  <line>Command: ./main.exe</line>
</preamble>

<pid>17842</pid>
<ppid>17831</ppid>
<tool>memcheck</tool>

<args>
  <vargv>
    <exe>/usr/bin/valgrind.bin</exe>
    <arg>--xml=yes</arg>
    <arg>--xml-file=valgrind.xml</arg>
    <arg>--demangle=yes</arg>
    <arg>--gen-suppressions=all</arg>
    <arg>--track-origins=yes</arg>
    <arg>--leak-check=full</arg>
    <arg>--show-reachable=no</arg>
    <arg>--num-callers=40</arg>
  </vargv>
  <argv>
    <exe>./main.exe</exe>
  </argv>
</args>

<status>
  <state>RUNNING</state>
  <time>00:00:00:00.040 </time>
</status>


<status>
  <state>FINISHED</state>
  <time>00:00:00:00.551 </time>
</status>

<errorcounts>
</errorcounts>

<suppcounts>
</suppcounts>

</valgrindoutput>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.