2009-12-14 41 views
10

Valgrind báo cáo rò rỉ bộ nhớ khi ấn định giá trị cho một chuỗi.Valgrind báo cáo rò rỉ bộ nhớ khi ấn định giá trị cho một chuỗi

Tôi đã sử dụng mã đơn giản sau đây để kiểm tra rò rỉ bộ nhớ được báo cáo bởi 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); 
} 

tôi biên dịch sử dụng lệnh này:

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

Và khi tôi chạy Valgrind nó báo cáo rò rỉ bộ nhớ khi tôi cố gắng gán một giá trị cho một chuỗi. Tôi đang sử dụng thử nghiệm đơn giản này để điều tra một số rò rỉ bộ nhớ trong chương trình thực, và có vẻ như việc sử dụng chuỗi có thể gây ra một số loại vấn đề.

Bởi 0x8048A6F: main (t3.c: 23) là dòng: string test = "XXXXXXXXX"; Ai đó có thể đưa ra một số gợi ý về hành vi kỳ lạ như vậy không?

[[email protected] 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 
[[email protected] C]$ 

Trả lời

43

Vì bạn gọi exit(0), do đó, trình hủy chuỗi không bao giờ được gọi. Chỉ cần sử dụng return 0.

Để xây dựng, hàm tạo của std::string phân bổ bộ nhớ heap để lưu trữ chuỗi, dựa vào destructor để deallocate bộ nhớ đó. Nếu bạn khai báo một đối tượng chuỗi trên ngăn xếp, hàm hủy sẽ tự động được gọi khi đối tượng chuỗi nằm ngoài phạm vi, do đó giải phóng bộ nhớ. Nhưng exit thực sự là một cơ chế C; nó ngay lập tức thoát khỏi chương trình mà không thực hiện ngăn xếp-thư giãn có nghĩa là C++ destructors cho các đối tượng stack cục bộ sẽ không được gọi.

3

Nếu bạn phân bổ năm chuỗi, bạn có bị mất gấp năm lần rò rỉ bộ nhớ hay không? Nếu đó là số tiền tương tự, thì có thể bạn sẽ không bị rò rỉ chút nào. Một số thư viện cấp phát bộ nhớ cho sổ sách kế toán/hiệu quả/vân vân nội bộ mà không được phát hành cho đến khi valgrind ngừng tìm kiếm. Chúng được chọn như là rò rỉ bộ nhớ bởi vì chương trình của bạn gây ra việc phân bổ nhưng không bao giờ gây ra một deallocation. Nếu số tiền đó gấp năm lần, thì việc triển khai chuỗi của bạn có thể bị lỗi. Tôi đồng ý với Charles Salvia mặc dù ... thử lại với return 0; thay vì exit(0); và xem điều đó có thay đổi gì không.

3

Trong một trong các lớp khoa học máy tính của tôi, chúng tôi được thông báo rằng Valgrind xuất thông tin về chuỗi mà chúng tôi không nên lo lắng. Dưới đây là file ức chế mà họ đã cho chúng tôi cho chuỗi: https://sites.google.com/site/complingfiles/files/string.supp

+0

Rất tiếc, liên kết được đề cập ở đây không còn hoạt động. – Riot

+0

Vâng, trường đã chuyển lớp đó sang java. Tôi sẽ xem tôi có thể đào nó ở bất cứ đâu không. –

+1

@Riot: tìm thấy tệp và đăng liên kết mới. –

2

Mặc dù không có exit(0) ở phần cuối của chương trình tôi có vấn đề tương tự với dương tính giả với std::string. Tôi đã liên kết tĩnh với libstdc++. Chuyển đổi tùy chọn liên kết để chia sẻ và biên dịch với GLIBCXX_FORCE_NEW đã chặn các cảnh báo.

+0

Cảm ơn bạn, cảm ơn bạn, cảm ơn bạn, cảm ơn bạn! –

+0

Dường như việc biên dịch với cờ 'GLIBCXX_FORCE_NEW' không thực sự làm gì cả. Theo [libstdC++ tài liệu cho mt_allocator] (https://gcc.gnu.org/onlinedocs/libstdc++/manual/mt_allocator_impl.html), đó là một biến môi trường. "Nếu biến môi trường GLIBCXX_FORCE_NEW được thiết lập, nó đặt bool _S_force_new thành true và sau đó trả về.". Vì vậy, chỉ cần làm một cái gì đó như 'xuất khẩu GLIBCXX_FORCE_NEW = 1;' và sau đó chạy valgrind. Điều này giải quyết rất nhiều vấn đề tôi đã có với std :: string cho dương tính giả. – BobTuckerman

Các vấn đề liên quan