2017-08-25 3 views
0

Sur une machine Linux, exécutez ce script pour compiler une petite application C++ et l'exécuter sous valgrind:Stack alloués std :: rapports de chaîne comme fuite de mémoire par 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 

La sortie de ce qui précède pour mon la machine RHEL 6.8 donne:

+ 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> 

en appliquant la variable GLIBCXX_FORCE_NEW comme indiqué dans la réponse https://stackoverflow.com/a/7284726/257924 n'a eu aucun effet. Donc, ma question est la suivante: est-ce un bug dans valgrind, dans la version de la bibliothèque standard C++ sur cette machine, ou ma propre mauvaise compréhension de la façon dont la bibliothèque C++ se déchire à ::exit() temps d'appel? Ma pensée actuelle est que je peux juste le supprimer dans valgrind et passer à autre chose.

+0

Note: Commentant l'appel à 'exit (0)' provoque l'erreur de valgrind disparaître. – bgoodr

+1

Oui, lorsque vous commentez la sortie, les retours principaux et le destructeur de la chaîne std :: string sont appelés et libèrent la mémoire. Notez que les nouvelles versions de valgrind comprennent mieux l'accessibilité de std :: string (voir ma réponse ci-dessous) – phd

Répondre

1

Vous utilisez une très ancienne version valgrind (3.8 .1), et donc vous ne bénéficiez pas des nouvelles fonctionnalités améliorées. Il y a quelques validations, quelques heuristiques liées à C++ ont été ajoutées à Valgrind, de sorte que a.o. pour mieux comprendre std :: string.

Notez que la sortie xml contient moins d'informations que la sortie textuelle (par exemple, ne donne pas de détails sur les heuristiques utilisées).

La dernière version de valgrind donne la sortie ci-dessous, montrant que la chaîne std :: a été reconnue en utilisant l'heuristique stdstring. Voir plus de détails sur heuristiques à 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) 
+0

Si j'avais l'option de mettre à niveau vers un système d'exploitation RHEL plus récent, et avec la chaîne de compilation gcc, je pourrais y remédier. Sans cela, je vais juste l'ignorer avec une suppression de valgrind. Je vous remercie! – bgoodr

+0

Notez qu'il est assez facile de compiler et d'installer votre propre version de valgrind. Mais sans cela, efficacement, une entrée de suppression est la voie à suivre. – phd

0

doit être un bug dans la bibliothèque standard C++ ou autre chose au-delà de mon contrôle immédiat, comme je l'ai retenté le script sur ma boîte Ubuntu et ai:

+ 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>