11

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]$
4

4 に答える 4

43

を呼び出すexit(0)ため、文字列デストラクタが呼び出されることはありません。を使用するだけreturn 0です。

詳細に説明すると、のコンストラクタはstd::stringヒープメモリを割り当てて文字列を格納し、デストラクタに依存してそのメモリの割り当てを解除します。スタック上で文字列オブジェクトを宣言すると、文字列オブジェクトがスコープ外になるとデストラクタが自動的に呼び出され、メモリが解放されます。しかし、これexitは実際にはCメカニズムです。スタックの巻き戻しを実行せずにプログラムをすぐに終了します。つまり、ローカルスタックオブジェクトのC++デストラクタは呼び出されません。

于 2009-12-14T14:51:41.090 に答える
3

5つの文字列を割り当てると、メモリリークが5倍になりますか、それとも同じ量ですか?同じ量であれば、おそらくリークはまったくありません。一部のライブラリは、valgrindが検索を停止するまで解放されない内部簿記/効率/その他にメモリを割り当てます。これらは、プログラムが割り当てを引き起こしたが、割り当て解除を引き起こさなかったため、メモリリークとして検出されます。量が5倍の場合は、文字列の実装に問題がある可能性があります。return 0;私はチャールズサルビアに同意します...代わりにもう一度試してexit(0);、それが何かを変えるかどうかを確認してください。

于 2009-12-14T15:20:51.067 に答える
3

プログラムの最後に何もなかったにもかかわらず、exit(0)私は誤検知で同様の問題がありましたstd::string. と静的にリンクしていましlibstdc++た。リンクオプションを共有に切り替えGLIBCXX_FORCE_NEW、警告を抑制してコンパイルしました。

于 2012-05-16T17:35:24.800 に答える
3

あるコンピュータ サイエンスのクラスで、Valgrind が文字列に関する情報を出力するが、心配する必要はないと言われました。彼らが私たちに提供した文字列の抑制ファイルは次のとおりです

于 2011-12-10T22:03:10.363 に答える