2010-09-10 69 views
2

我沒有看到下面泄漏的原因。C++ valgrind STL字符串可能泄漏

#include <iostream> 
#include <cstdlib> 

int fail(const std::string str) 
{ 
    std::cerr<< str << std::endl; 
    exit(1); 
} 

const std::string usage() 
{ 
    std::string a = "a"; 
    return a; 
} 

int main() 
{ 
    fail(usage()); 
    return 0; 
} 

Valgrind的說:

==7238== 14 bytes in 1 blocks are possibly lost in loss record 1 of 1 
==7238== at 0x402377E: operator new(unsigned) (vg_replace_malloc.c:224) 
==7238== by 0x40E7C03: std::string::_Rep::_S_create(unsigned, unsigned, 
std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.10) 
==7238== by 0x40E8864: (within /usr/lib/libstdc++.so.6.0.10) 
==7238== by 0x40E89D5: std::string::string(char const*, std::allocator<char> const&) 
(in /usr/lib/libstdc++.so.6.0.10) 
==7238== by 0x80488EC: usage() (main.cpp:12) 
==7238== by 0x804897C: main (main.cpp:18) 
==7238== LEAK SUMMARY: 
==7238== definitely lost: 0 bytes in 0 blocks. 
==7238==  possibly lost: 14 bytes in 1 blocks. 
==7238== still reachable: 0 bytes in 0 blocks. 
==7238==   suppressed: 0 bytes in 0 blocks. 

的問題是在失敗()函數。當它退出()時,內存泄漏。

如果我註釋退出(1);那麼就沒有可能的泄漏。

另外,如果我從 INT更改簽名失敗(常量的std :: string STR) 到 INT失敗(爲const char * STR)

那麼有沒有可能發生泄漏的爲好。我不喜歡這個解決方案,因爲我正在使用fail(string +(LINE))類型的東西,但無論如何,這裏發生了什麼?

如果有人能解釋我會很高興。

謝謝!

(UPPS。同樣的問題問我猜想之前,對不起!Valgrind reports memory leak when assigning a value to a string

回答

21

當你調用exit(),自動對象(局部變量)的析構函數不會被調用。

在您的具體示例中,std::string析構函數未被調用,因此std::string所擁有的內存永遠不會被釋放。

如果您有fail()需要const char*,沒有泄漏的原因是const char*沒有析構函數;當指針被銷​​毀時,沒有任何東西被釋放。如果指針指向動態分配的內存,那麼在程序退出之前必須將該內存解除分配(否則),否則會導致內存泄漏。如果它指向一個字符串文字,那麼就沒有內存泄漏,因爲字符串文字具有靜態存儲持續時間(也就是說,它們存在於程序的整個生命週期中)。

+1

本文說你錯了:http://www.cplusplus.com/reference/clibrary/cstdlib/exit/ – Klaim 2010-09-10 19:07:40

+10

@Klaim:我沒有看到那個文件說我錯了,但如果它那麼這是錯誤的。引用C++標準(§18。3/8):「自動對象不會因爲調用'exit()'而被銷燬。」 – 2010-09-10 19:11:39

+0

然後那句話「正常結束進程,執行終止進程的定期清理」。是誤導?無論如何,標準說你是對的,所以你是對的。 (不能投票,直到你編輯雖然) – Klaim 2010-09-10 19:14:29

8

詹姆斯麥克奈利斯已經寫了一個正確的答案。但我想補充一些東西:

  1. 它始終是一個方式來寫軟件,它並沒有調用exit()是一件好事 - 這可以幫助您提高整體設計,指定和了解對象的生命週期(除了非常特殊的情況 - 相當低的情況下)。

  2. 正如你在這裏看到的,當使用像valgrind這樣的工具時這很重要!一個「乾淨的」關機程序讓你感覺安全,然後一切正常,如你所料;)在特殊情況下的乾淨關機程序應該是每個軟件的要求。

你應該考慮到throw一個例外,而不是調用一些fail()功能。當拋出異常時,堆棧將被解開,所以你的案例中的std::string析構函數會被調用。