Распределенный в стеке std::string сообщает об утечке памяти valgrind

На компьютере с Linux запустите этот скрипт, чтобы скомпилировать небольшое приложение C++ и запустить его под управлением 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

Вывод выше для моей машины RHEL 6.8 дает:

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

Применение переменной GLIBCXX_FORCE_NEW, как указано в ответе https://stackoverflow.com/a/7284726/257924, не дало никакого эффекта.

Итак, мой вопрос таков: это ошибка в valgrind, в версии стандартной библиотеки С++ на этой машине или мое собственное непонимание того, как библиотека С++ разрывается во время/во время вызова ::exit()?

В настоящее время я думаю, что я могу просто подавить его в valgrind и двигаться дальше.


person bgoodr    schedule 25.08.2017    source источник
comment
Примечание. Закомментирование вызова exit(0) приводит к исчезновению ошибки valgrind.   -  person bgoodr    schedule 25.08.2017
comment
Да, когда вы закомментируете выход, то main возвращается, вызывается деструктор std::string и освобождает память. Обратите внимание, что более новые версии valgrind лучше понимают доступность std::string (см. мой ответ ниже)   -  person phd    schedule 25.08.2017


Ответы (2)


Вы используете очень старую версию valgrind (3.8.1) и поэтому не получаете преимуществ от новых улучшенных функций. Некоторые выпуски valgrind назад, некоторые эвристики, связанные с C++, были добавлены в Valgrind, так как a.o. чтобы лучше понять std::string.

Обратите внимание, что вывод в формате xml содержит меньше информации, чем текстовый вывод (например, не содержит сведений об используемых эвристиках).

Последняя версия valgrind дает приведенный ниже вывод, показывающий, что std::string был распознан с использованием эвристики stdstring. Дополнительные сведения об эвристике см. на странице 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)
person phd    schedule 25.08.2017
comment
Если бы у меня была возможность перейти на более новую ОС RHEL, а вместе с ней и набор инструментов компилятора gcc, я мог бы облегчить это. Без этого я просто проигнорирую это с помощью подавления valgrind. Спасибо! - person bgoodr; 26.08.2017
comment
Обратите внимание, что довольно легко скомпилировать и установить собственную версию valgrind. Но и без этого, по сути, вход с подавлением — это путь. - person phd; 26.08.2017

Должна быть ошибка в стандартной библиотеке C++ или что-то еще, находящееся вне моего непосредственного контроля, поскольку я повторил сценарий на своем компьютере с Ubuntu и получил:

+ 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>
person bgoodr    schedule 25.08.2017