Valgrind сообщает об утечке памяти при назначении значения в строку - PullRequest
10 голосов
/ 14 декабря 2009

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 ]

43 голосов
/ 14 декабря 2009

Поскольку вы вызываете exit(0), то деструктор строки никогда не вызывается. Просто используйте return 0.

Чтобы уточнить, конструктор std::string выделяет кучу памяти для хранения строки, полагаясь на деструктор для освобождения этой памяти. Если вы объявляете строковый объект в стеке, деструктор будет автоматически вызываться, когда строковый объект выходит из области видимости, освобождая память. Но exit действительно механизм C; он немедленно выходит из программы без выполнения разматывания стека, что означает, что деструкторы C ++ для локальных объектов стека не будут вызываться.

3 голосов
/ 11 декабря 2011

На одном из моих уроков информатики нам сказали, что Valgrind выводит информацию о строках, о которых нам не следует беспокоиться. Вот файл подавления, который нам дали для строк: https://sites.google.com/site/complingfiles/files/string.supp

3 голосов
/ 14 декабря 2009

Если вы выделите пять строк, у вас будет пять раз утечка памяти, или это все тот же объем? Если это то же самое количество, то у вас, вероятно, нет утечки вообще. Некоторые библиотеки выделяют память для внутренней бухгалтерии / эффективности / и так далее, которая не освобождается до тех пор, пока valgrind не перестанет искать. Они воспринимаются как утечки памяти, потому что ваша программа вызывала выделение, но никогда не вызывала освобождение. Если это в пять раз больше, то ваша реализация строки может быть ошибочной. Я согласен с Чарльзом Сальвией, хотя ... попробуйте еще раз с return 0; вместо exit(0); и посмотрите, изменит ли это что-нибудь.

2 голосов
/ 16 мая 2012

Несмотря на отсутствие exit(0) в конце программы, у меня была похожая проблема с ложными срабатываниями с std::string. Я статически связывался с libstdc++. Переключение опции связывания на общий и компиляция с GLIBCXX_FORCE_NEW подавили предупреждения.

...