堆栈分配 std::string 报告为 valgrind 的内存泄漏
Stack-allocated std::string reports as memory leak by 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<char> const&)</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<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)</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
变量没有效果。
所以我的问题是:这是 valgrind 中的一个错误,在这台机器上的 C++ 标准库版本中,还是我自己对 C++ 库如何被拆除的误解 at/near ::exit()
通话时间?
我目前的想法是我应该在 valgrind 中抑制它然后继续。
一定是标准 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>
您使用的是非常旧的 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)
在 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<char> const&)</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<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)</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
变量没有效果。
所以我的问题是:这是 valgrind 中的一个错误,在这台机器上的 C++ 标准库版本中,还是我自己对 C++ 库如何被拆除的误解 at/near ::exit()
通话时间?
我目前的想法是我应该在 valgrind 中抑制它然后继续。
一定是标准 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>
您使用的是非常旧的 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)