valgrind报告内存泄漏时,给字符串赋值 [英] valgrind report memory leak when assign a value to a string

查看:106
本文介绍了valgrind报告内存泄漏时,给字符串赋值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当为字符串赋值时,Valgrind报告内存泄漏



我使用这个简单的代码来测试valgrind报告的内存泄漏。

  / ******************************** ********** 
* FILE:t3.c
*编译时使用:g ++ -g t3.c -o t3
*
* $ g ++ - v
*从/usr/lib/gcc/i686-pc-linux-gnu/3.4.6/specs读取规格
*配置为:./configure --prefix = / usr --infodir = / share / info --mandir = / share / man
* --enable-languages = c,c ++ --with-system-zlib --program- suffix = -3.4 --enable-threads = posix
*主题模特:posix
* gcc版本3.4.6
*************************** ************* /


#include< iostream>
#include< string>

using namespace std;

/ ***************************************** *********************
************************* ************************************* /
int main(int argc,char * argv [])
{
string test =XXXXXXXXX;
cout<< 这是一个测试<测试< endl;
exit(0);
}

我使用此命令编译
$ g ++ -g t3.c -o t3



当我运行valgrind它报告一个内存泄漏,当我尝试分配一个字符串值。
我使用这个简单的测试调查一些memoru泄漏在真正的程序,似乎使用字符串可以导致一些问题。



通过0x8048A6F:main(t3.c:23)是行:string test =XXXXXXXXX;
有人能对这种奇怪的行为给出一些提示吗?
谨慎,Enzo

  [enzo @ P0101222 C] $ valgrind --leak-check = full ./t3 
== 3910 == Memcheck,一个内存错误检测器。
== 3910 ==版权所有(C)2002-2007,以及GNU GPL'd,由Julian Seward等人
== 3910 ==使用LibVEX rev 1732,一个动态二进制翻译库。
== 3910 ==版权所有(C)2004-2007,以及OpenWorks LLP的GNU GPL'd。
== 3910 ==使用valgrind-3.2.3,一个动态二进制工具框架。
== 3910 ==版权所有(C)2000-2007,和GNU GPL'd,由Julian Seward等人
== 3910 ==更多细节,重新运行:-v
== 3910 ==
这是一个测试XXXXXXXXX
== 3910 ==
= = 3910 == ERROR摘要:0个上下文中的0个错误(抑制:25个从1)
== 3910 == malloc / free:在退出时使用:3个块中的102个字节。
== 3910 == malloc / free:4 allocs,1 frees,126 bytes allocated。
== 3910 ==对于检测到的错误计数,重新运行:-v
== 3910 ==搜索指向3个未释放的块的指针。
== 3910 ==检查194,136字节。
== 3910 ==
== 3910 == 1个块中的16个字节绝对会在丢失记录中丢失1个3
== 3910 == 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(在/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 == 1个块中的22个字节可能在丢失记录2中丢失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 ==漏洞摘要:
== 3910 ==绝对丢失:1个块中的16个字节。
== 3910 == **可能丢失:1个块中有22个字节**
== 3910 ==仍然可达:1个块中有64个字节。
== 3910 == suppressed:0个字节在0块。
== 3910 ==不显示可访问块(找到指针的块)。
== 3910 ==查看它们,重新运行:--leak-check = full --show-reachable = yes
[enzo @ P0101222 C] $
exit(0)
,所以字符串析构函数从不被调用。只需使用 return 0



要详细说明, std :: string 分配堆内存来存储字符串,依赖析构函数来释放内存。如果在堆栈上声明一个字符串对象,当字符串对象超出范围时,析构函数将被自动调用,从而释放内存。但是 exit 实际上是一个C机制;它立即退出程序而不执行stack-unwinding意味着本地堆栈对象的C ++析构函数不会被调用。


Valgrind report memory leak when assign a value to a string

I used this 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 report a memory leak when I try to assign a value to a string. I'm using this simple test to investigate some memoru 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 ? Regards, Enzo

[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. Just use return 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. But exit 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报告内存泄漏时,给字符串赋值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆