为什么在一种情况下而不是在另一种情况下内存泄漏

时间:2019-01-02 14:06:43

标签: c++ memory-leaks valgrind

我正在以两种略有不同的方式创建一个c++对象,在以下代码中,当CASE0时,存在内存泄漏,但是{{1 }}。

else

当我设置#include <string> #define CASE 1 class A { private: std::string *s; public: A(std::string *p_s) { s = p_s; } }; int main() { #if CASE==0 auto a = A(new std::string("Hello")); #else auto s = std::string("Hello"); auto a = A(&s); #endif } 时,CASE 0说存在内存泄漏

valgrind

在其他情况下(即valgrind ./a.out ==24351== Memcheck, a memory error detector ==24351== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==24351== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==24351== Command: ./a.out ==24351== ==24351== ==24351== HEAP SUMMARY: ==24351== in use at exit: 32 bytes in 1 blocks ==24351== total heap usage: 2 allocs, 1 frees, 72,736 bytes allocated ==24351== ==24351== LEAK SUMMARY: ==24351== definitely lost: 32 bytes in 1 blocks ==24351== indirectly lost: 0 bytes in 0 blocks ==24351== possibly lost: 0 bytes in 0 blocks ==24351== still reachable: 0 bytes in 0 blocks ==24351== suppressed: 0 bytes in 0 blocks ==24351== Rerun with --leak-check=full to see details of leaked memory ==24351== ==24351== For counts of detected and suppressed errors, rerun with: -v ==24351== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) ),它按预期工作,并且valgrind不报告任何内存泄漏。

无论哪种情况,我都无法理解我正在传递指针,也没有显式地释放内存,那么为什么它们的行为有所不同?

4 个答案:

答案 0 :(得分:5)

此行为的原因是您的类A并非旨在获取传递给它的std::string*的所有权:其std::string *s成员假定该对象是要传递的指针进入构造函数将在外部被破坏。

当对象没有被破坏时,这会导致内存泄漏:delete永远不会在传递给构造函数的new string上调用,从而导致内存泄漏。

在第二种情况下,指针指向自动存储中的字符串。 main结束时它会被销毁,从而防止内存泄漏。

答案 1 :(得分:4)

因为有指针,所以不会发生内存泄漏。

内存泄漏是因为您new想要但没有delete

获取指向自动存储变量的指针不会阻止该变量被自动清除。

实际上,在这种情况下尝试delete &a是错误/破碎/邪恶/非法/异端。

答案 2 :(得分:1)

这与以下内容没有什么不同:

// first case, leak
int *j = new int (5);
//
// second case, no leak
int q = 5;
int *j = &q;

在第一种情况下,我们使用new分配了内存,完成后delete是我们的责任。在第二种情况下,我们在堆栈上创建q,并在超出范围时将其销毁。

答案 3 :(得分:1)

CASE == 0

auto a = A(new std::string("Hello"));

这意味着您正在new-正在堆中的对象->您必须明确 delete它-您不在代码段中->内存泄漏

其他

auto s = std::string("Hello");
auto a = A(&s);
  • auto s = std::string("Hello");:这意味着您正在堆栈中创建对象,并且
  • auto a = A(&s);:获取地址(当然是在堆栈中)。
  • 一旦变量超出范围,创建的对象将被自动删除

->没有内存泄漏。