Valgrind 在给字符串赋值时报告内存泄漏
Valgrind 在为字符串赋值时报告内存泄漏。
我使用以下简单代码来测试 Valgrind 报告的内存泄漏。
/******************************************
* FILE: t3.c
* Compiled using : g++ -g t3.c -o t3
*
* $ g++ -v
* Reading specs from /usr/lib/gcc/i686-pc-linux-gnu/3.4.6/specs
* Configured with: ./configure --prefix=/usr --infodir=/share/info --mandir=/share/man
* --enable-languages=c,c++ --with-system-zlib --program-suffix=-3.4 --enable-threads=posix
* Thread model: posix
* gcc version 3.4.6
******************************************/
#include <iostream>
#include <string>
using namespace std;
/**************************************************************
**************************************************************/
int main(int argc, char *argv[])
{
string test = "XXXXXXXXX";
cout << "this is a test " << test << endl;
exit(0);
}
我使用以下命令进行编译:
$ g++ -g t3.c -o t3
当我运行 Valgrind 时,当我尝试为字符串赋值时,它会报告内存泄漏。我正在使用这个简单的测试来调查实际程序中的一些内存泄漏,并且似乎使用字符串可能会导致某种问题。
通过 0x8048A6F: main (t3.c:23) 是行: string test = "XXXXXXXXX"; 有人可以对这种奇怪的行为给出一些提示吗?
[enzo@P0101222 C]$ valgrind --leak-check=full ./t3
==3910== Memcheck, a memory error detector.
==3910== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==3910== Using LibVEX rev 1732, a library for dynamic binary translation.
==3910== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==3910== Using valgrind-3.2.3, a dynamic binary instrumentation framework.
==3910== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==3910== For more details, rerun with: -v
==3910==
this is a test XXXXXXXXX
==3910==
==3910== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 25 from 1)
==3910== malloc/free: in use at exit: 102 bytes in 3 blocks.
==3910== malloc/free: 4 allocs, 1 frees, 126 bytes allocated.
==3910== For counts of detected errors, rerun with: -v
==3910== searching for pointers to 3 not-freed blocks.
==3910== checked 194,136 bytes.
==3910==
==3910== 16 bytes in 1 blocks are definitely lost in loss record 1 of 3
==3910== at 0x4017846: malloc (m_replacemalloc/vg_replace_malloc.c:149)
==3910== by 0x4018E05: realloc (m_replacemalloc/vg_replace_malloc.c:306)
==3910== by 0x41B441A: argz_append (in /lib/libc-2.2.5.so)
==3910== by 0x41593B9: __newlocale (in /lib/libc-2.2.5.so)
==3910== by 0x40E010B: std::locale::facet::_S_create_c_locale(__locale_struct*&, char const*, __locale_struct*) (c++locale.cc:99)
==3910== by 0x407EF6F: std::locale::facet::_S_initialize_once() (../../.././libstdc++-v3/src/locale.cc:172)
==3910== by 0x407EFB4: std::locale::facet::_S_get_c_locale() (../../.././libstdc++-v3/src/locale.cc:185)
==3910== by 0x407A422: std::ctype<char>::ctype(unsigned short const*, bool, unsigned) (/usr3/BUILD/gcc/gcc-3.4.6/i686-pc-linux-gnu/libstdc++-v3/include/i686-pc-linux-gnu/bits/ctype_noninline.h:104)
==3910== by 0x40801D5: std::locale::_Impl::_Impl(unsigned) (/usr3/BUILD/gcc/gcc-3.4.6/libstdc++-v3/libsupc++/new:92)
==3910== by 0x4080EED: std::locale::_S_initialize_once() (/usr3/BUILD/gcc/gcc-3.4.6/libstdc++-v3/libsupc++/new:92)
==3910== by 0x4080F84: std::locale::_S_initialize() (../../.././libstdc++-v3/src/locale_init.cc:155)
==3910== by 0x4080FE7: std::locale::locale() (../../.././libstdc++-v3/src/locale_init.cc:102)
==3910==
==3910==
==3910== 22 bytes in 1 blocks are possibly lost in loss record 2 of 3
==3910== at 0x4017C38: operator new(unsigned) (m_replacemalloc/vg_replace_malloc.c:163)
==3910== by 0x40BF2C4: std::string::_Rep::_S_create(unsigned, unsigned, std::allocator<char> const&) (/usr3/BUILD/gcc/gcc-3.4.6/i686-pc-linux-gnu/libstdc++-v3/include/ext/new_allocator.h:81)
==3910== by 0x40C1CE4: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (/usr3/BUILD/gcc/gcc-3.4.6/i686-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.tcc:150)
==3910== by 0x40C1E15: std::string::string(char const*, std::allocator<char> const&) (/usr3/BUILD/gcc/gcc-3.4.6/i686-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:1386)
==3910== **by 0x8048A6F: main (t3.c:23)**
==3910==
==3910== LEAK SUMMARY:
==3910== definitely lost: 16 bytes in 1 blocks.
==3910== **possibly lost: 22 bytes in 1 blocks.**
==3910== still reachable: 64 bytes in 1 blocks.
==3910== suppressed: 0 bytes in 0 blocks.
==3910== Reachable blocks (those to which a pointer was found) are not shown.
==3910== To see them, rerun with: --leak-check=full --show-reachable=yes
[enzo@P0101222 C]$
Valgrind reports a memory leak when assigning a value to a string.
I used the following simple code to test an memory leak reported by Valgrind.
/******************************************
* FILE: t3.c
* Compiled using : g++ -g t3.c -o t3
*
* $ g++ -v
* Reading specs from /usr/lib/gcc/i686-pc-linux-gnu/3.4.6/specs
* Configured with: ./configure --prefix=/usr --infodir=/share/info --mandir=/share/man
* --enable-languages=c,c++ --with-system-zlib --program-suffix=-3.4 --enable-threads=posix
* Thread model: posix
* gcc version 3.4.6
******************************************/
#include <iostream>
#include <string>
using namespace std;
/**************************************************************
**************************************************************/
int main(int argc, char *argv[])
{
string test = "XXXXXXXXX";
cout << "this is a test " << test << endl;
exit(0);
}
I compile using this command:
$ g++ -g t3.c -o t3
And when I run Valgrind it reports a memory leak when I try to assign a value to a string. I'm using this simple test to investigate some memory leak in the real program, and it seems that using string can cause some sort of problem.
By 0x8048A6F: main (t3.c:23) is the line : string test = "XXXXXXXXX";
Can someone give some hint on such strange behaviour?
[enzo@P0101222 C]$ valgrind --leak-check=full ./t3
==3910== Memcheck, a memory error detector.
==3910== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==3910== Using LibVEX rev 1732, a library for dynamic binary translation.
==3910== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==3910== Using valgrind-3.2.3, a dynamic binary instrumentation framework.
==3910== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==3910== For more details, rerun with: -v
==3910==
this is a test XXXXXXXXX
==3910==
==3910== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 25 from 1)
==3910== malloc/free: in use at exit: 102 bytes in 3 blocks.
==3910== malloc/free: 4 allocs, 1 frees, 126 bytes allocated.
==3910== For counts of detected errors, rerun with: -v
==3910== searching for pointers to 3 not-freed blocks.
==3910== checked 194,136 bytes.
==3910==
==3910== 16 bytes in 1 blocks are definitely lost in loss record 1 of 3
==3910== at 0x4017846: malloc (m_replacemalloc/vg_replace_malloc.c:149)
==3910== by 0x4018E05: realloc (m_replacemalloc/vg_replace_malloc.c:306)
==3910== by 0x41B441A: argz_append (in /lib/libc-2.2.5.so)
==3910== by 0x41593B9: __newlocale (in /lib/libc-2.2.5.so)
==3910== by 0x40E010B: std::locale::facet::_S_create_c_locale(__locale_struct*&, char const*, __locale_struct*) (c++locale.cc:99)
==3910== by 0x407EF6F: std::locale::facet::_S_initialize_once() (../../.././libstdc++-v3/src/locale.cc:172)
==3910== by 0x407EFB4: std::locale::facet::_S_get_c_locale() (../../.././libstdc++-v3/src/locale.cc:185)
==3910== by 0x407A422: std::ctype<char>::ctype(unsigned short const*, bool, unsigned) (/usr3/BUILD/gcc/gcc-3.4.6/i686-pc-linux-gnu/libstdc++-v3/include/i686-pc-linux-gnu/bits/ctype_noninline.h:104)
==3910== by 0x40801D5: std::locale::_Impl::_Impl(unsigned) (/usr3/BUILD/gcc/gcc-3.4.6/libstdc++-v3/libsupc++/new:92)
==3910== by 0x4080EED: std::locale::_S_initialize_once() (/usr3/BUILD/gcc/gcc-3.4.6/libstdc++-v3/libsupc++/new:92)
==3910== by 0x4080F84: std::locale::_S_initialize() (../../.././libstdc++-v3/src/locale_init.cc:155)
==3910== by 0x4080FE7: std::locale::locale() (../../.././libstdc++-v3/src/locale_init.cc:102)
==3910==
==3910==
==3910== 22 bytes in 1 blocks are possibly lost in loss record 2 of 3
==3910== at 0x4017C38: operator new(unsigned) (m_replacemalloc/vg_replace_malloc.c:163)
==3910== by 0x40BF2C4: std::string::_Rep::_S_create(unsigned, unsigned, std::allocator<char> const&) (/usr3/BUILD/gcc/gcc-3.4.6/i686-pc-linux-gnu/libstdc++-v3/include/ext/new_allocator.h:81)
==3910== by 0x40C1CE4: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (/usr3/BUILD/gcc/gcc-3.4.6/i686-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.tcc:150)
==3910== by 0x40C1E15: std::string::string(char const*, std::allocator<char> const&) (/usr3/BUILD/gcc/gcc-3.4.6/i686-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:1386)
==3910== **by 0x8048A6F: main (t3.c:23)**
==3910==
==3910== LEAK SUMMARY:
==3910== definitely lost: 16 bytes in 1 blocks.
==3910== **possibly lost: 22 bytes in 1 blocks.**
==3910== still reachable: 64 bytes in 1 blocks.
==3910== suppressed: 0 bytes in 0 blocks.
==3910== Reachable blocks (those to which a pointer was found) are not shown.
==3910== To see them, rerun with: --leak-check=full --show-reachable=yes
[enzo@P0101222 C]$
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
因为您调用了 exit(0),所以永远不会调用字符串析构函数。只需使用
return 0
即可。详细来说,std::string 的构造函数分配堆内存来存储字符串,并依赖析构函数来释放该内存。如果在堆栈上声明一个字符串对象,当该字符串对象超出范围时,析构函数将自动被调用,从而释放内存。但
exit
实际上是一种 C 机制;它立即退出程序而不执行堆栈展开,这意味着不会调用本地堆栈对象的 C++ 析构函数。Because you call
exit(0)
, so the string destructor is never invoked. Just usereturn 0
.To elaborate, the constructor of
std::string
allocates heap memory to store the string, relying on the destructor to deallocate that memory. If you declare a string object on the stack, the destructor will automatically be invoked when the string object goes out of scope, thus freeing the memory. Butexit
is really a C mechanism; it immediately exits the program without performing stack-unwinding meaning that C++ destructors for local stack objects will not be called.如果你分配五个字符串,你会得到五倍的内存泄漏,还是仍然是相同的数量?如果数量相同,则可能根本没有泄漏。一些库为内部簿记/效率等分配内存,直到 valgrind 停止查找后才会释放内存。这些被认为是内存泄漏,因为您的程序导致了分配,但从未导致释放。如果它是该数量的五倍,那么您的字符串实现可能有问题。不过,我同意 Charles Salvia 的观点……用
return 0;
而不是exit(0);
再次尝试,看看是否会改变任何内容。If you allocate five strings, do you get five times the memory leak, or is it still the same amount? If it's the same amount, then you probably don't have a leak at all. Some libraries allocate memory for internal bookkeeping/efficiency/et cetera that doesn't get released until after valgrind stops looking. These get picked up as memory leaks because your program caused the allocation but never caused a deallocation. If it's five times the amount, then your implementation of string may be at fault. I agree with Charles Salvia though... try again with
return 0;
instead ofexit(0);
and see if that changes anything.尽管程序末尾没有
exit(0)
,但我在std::string
中也遇到了类似的误报问题。我静态链接到libstdc++
。将链接选项切换为共享并使用GLIBCXX_FORCE_NEW
进行编译可抑制警告。Despite having no
exit(0)
at the end of program I had similar problem with false positives withstd::string
. I was statically linking withlibstdc++
. Switching linking option to shared and compiling withGLIBCXX_FORCE_NEW
suppressed the warnings.在我的一门计算机科学课程中,我们被告知 Valgrind 输出有关我们不应该担心的字符串的信息。这是他们为我们提供的字符串抑制文件:
https://gist.github.com/garfieldnate/eb7ba0011b57a9c63e7c3dcafb689e15
In one of my computer science classes we were told that Valgrind outputs information about strings that we shouldn't worry about. Here's the suppression file that they gave us for strings:
https://gist.github.com/garfieldnate/eb7ba0011b57a9c63e7c3dcafb689e15