简体   繁体   English

Valgrind为字符串分配值时报告内存泄漏

[英]Valgrind reports memory leak when assigning a value to a string

Valgrind reports a memory leak when assigning a value to a string. 为字符串分配值时,Valgrind报告内存泄漏。

I used the following simple code to test an memory leak reported by 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);
}

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. 当我运行Valgrind时,它在尝试为字符串分配值时报告内存泄漏。 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"; 通过0x8048A6F:main(t3.c:23)是该行: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]$

Because you call exit(0) , so the string destructor is never invoked. 因为您调用exit(0) ,所以永远不会调用字符串析构函数。 Just use return 0 . 只需使用return 0

To elaborate, the constructor of std::string allocates heap memory to store the string, relying on the destructor to deallocate that memory. 详细说来, std::string的构造函数分配堆内存来存储字符串,它依赖于析构函数来释放该内存。 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. 如果在堆栈上声明一个字符串对象,则当该字符串对象超出范围时,析构函数将自动被调用,从而释放内存。 But exit is really a C mechanism; 但是exit实际上是一种C机制。 it immediately exits the program without performing stack-unwinding meaning that C++ destructors for local stack objects will not be called. 它会立即退出程序而不执行堆栈展开操作,这意味着将不会调用本地堆栈对象的C ++析构函数。

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. 一些库为内部记账/效率/其他分配内存,直到valgrind停止查找后才释放。 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; 我同意查尔斯·萨尔维亚(Charles Salvia)的观点,然后重试return 0; instead of exit(0); 而不是exit(0); and see if that changes anything. 看看是否有任何改变。

In one of my computer science classes we were told that Valgrind outputs information about strings that we shouldn't worry about. 在我的一门计算机科学课程中,我们被告知Valgrind输出有关字符串的信息,这些信息我们我们不必担心。 Here's the suppression file that they gave us for strings: https://sites.google.com/site/complingfiles/files/string.supp 这是他们为我们提供的禁止字符串: https : //sites.google.com/site/complingfiles/files/string.supp

Despite having no exit(0) at the end of program I had similar problem with false positives with std::string . 尽管在程序末尾没有exit(0) ,但std::string误报也有类似的问题。 I was statically linking with libstdc++ . 我与libstdc++静态链接。 Switching linking option to shared and compiling with GLIBCXX_FORCE_NEW suppressed the warnings. 将链接选项切换为共享并使用GLIBCXX_FORCE_NEW编译可禁止显示警告。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM