Domanda

Valgrind riporta una perdita di memoria quando si assegna un valore in una stringa.

Ho usato il seguente codice semplice per testare una perdita di memoria riportato da 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);
}

compilo con questo comando:

$ g++ -g t3.c -o t3

E quando corro Valgrind riporta una perdita di memoria quando si tenta di assegnare un valore a una stringa. Sto usando questo semplice test per indagare su alcuni perdita di memoria nel programma vero e proprio, e sembra che l'uso di stringa può causare qualche tipo di problema.

Per 0x8048A6F: main (t3.c: 23) è la linea: prova stringa = "XXXXXXXXX"; Qualcuno può dare qualche suggerimento su come strano comportamento?

[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]$
È stato utile?

Soluzione

Perché si chiama exit(0), in modo che il distruttore stringa viene mai richiamato. Basta usare return 0.

Per elaborare, il costruttore di std::string alloca memoria heap per memorizzare la stringa, basandosi sul distruttore deallocare quella memoria. Se si dichiara una stringa di oggetto in pila, il distruttore sarà automaticamente richiamato quando l'oggetto stringa va fuori del campo di applicazione, liberando così la memoria. Ma exit è davvero un meccanismo di C; esce immediatamente il programma senza eseguire significato stack svolgimento che C ++ distruttori per gli oggetti pila locali non saranno chiamati.

Altri suggerimenti

Se si alloca cinque corde, si ottiene cinque volte la perdita di memoria, o è ancora la stessa quantità? Se è la stessa quantità, allora probabilmente non si dispone di una perdita a tutti. Alcune librerie allocare memoria per la contabilità interna / efficienza / eccetera che non viene rilasciato fino a dopo valgrind smette di guardare. Questi vengono raccolti come le perdite di memoria perché il programma ha causato l'assegnazione, ma non ha causato una deallocazione. Se si tratta di cinque volte l'importo, quindi l'implementazione di stringa può essere in difetto. Sono d'accordo con Charles Salvia però ... prova di nuovo con return 0; invece di exit(0); e vedere se questo cambia nulla.

In uno dei miei corsi di informatica ci hanno detto che Valgrind emette informazioni sulle stringhe che non si deve preoccupare. Ecco il file di soppressione che ci hanno dato per le stringhe: https://sites.google.com/site/complingfiles/files/string. supp

Pur avendo alcun exit(0) alla fine del programma ho avuto problema simile con falsi positivi con std::string. Mi è stato staticamente il collegamento con libstdc++. Passaggio che collega possibilità di condivisione e la compilazione con GLIBCXX_FORCE_NEW soppresse le avvertenze.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top