2010-09-10 56 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析构函数会被调用。