内存泄漏,我不知道为什么

memory leak and I don't know why

我的第一个问题是添加了地图的对象 A(v),它应该在退出范围时自动删除吗?

我的第二个问题是当程序退出时添加到地图中的对象会发生什么?我相信当我执行 a_[name] = A(v); 时,副本会存储到地图中。 还有,需要提供拷贝构造函数吗?

void B::AddA(std::string name, int v) {
    a_[name] = A(v);
}

我的最后一个问题是我没有用“new”创建任何对象,我不需要删除任何对象。

我不明白泄漏是从哪里来的。

感谢任何帮助。谢谢。

完整代码

#include <map>
#include <string>
#include <iostream>

class A {
    public:
        int vala_;
        A();
        ~A();
        A(int v);
};

A::A() {
    vala_ = 0;
}

A::~A() {}

A::A(int v) {
    vala_ = v;
}


class B {
    public:
        int valb_;
        std::map<std::string, A> a_;
        B();
        ~B();
        void AddA(std::string name, int v);
};

B::B() {
    valb_ = 0;
}

B::~B() {
}

void B::AddA(std::string name, int v) {
    a_[name] = A(v);
}


int main() {
    B b;
    b.AddA("wewe", 5);
    std::cout << b.a_["wewe"].vala_ << std::endl;
    exit(0);
}

valgrind

I replaced the number ==????==, to ==xxxx==. I guess it was the process id. 
==xxxx== Memcheck, a memory error detector
==xxxx== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==xxxx== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==xxxx== Command: ./a.out --leak-check=full -s
==xxxx==
5
==xxxx==
==xxxx== HEAP SUMMARY:
==xxxx==     in use at exit: 72 bytes in 1 blocks
==xxxx==   total heap usage: 3 allocs, 2 frees, 73,800 bytes allocated
==xxxx==
==xxxx== LEAK SUMMARY:
==xxxx==    definitely lost: 0 bytes in 0 blocks
==xxxx==    indirectly lost: 0 bytes in 0 blocks
==xxxx==      possibly lost: 0 bytes in 0 blocks
==xxxx==    still reachable: 72 bytes in 1 blocks
==xxxx==         suppressed: 0 bytes in 0 blocks
==xxxx== Rerun with --leak-check=full to see details of leaked memory
==xxxx==
==xxxx== For lists of detected and suppressed errors, rerun with: -s
==xxxx== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

“仍然可达”并不严格意味着它是 memory leak。我相信这是因为你调用了 exit(0) 而不是只返回 0。堆栈没有被清理,因为程序被信号终止了。

==xxxx==     in use at exit: 72 bytes in 1 blocks

==xxxx==    still reachable: 72 bytes in 1 blocks

这些仅意味着当程序退出时仍然存在您仍然有引用的活动内存。内存并没有完全丢失,这就是通常所说的严格意义上的内存泄漏,在definitely lostindirectly lostpossibly lost下列出。当程序结束时,是否还有未释放的内存并不重要。

然而,这仍然可能是一个问题的迹象,例如,如果应该被销毁并且具有带有副作用的析构函数的对象不是 运行。

在您的情况下,问题是 exit(0) 调用。调用 std::exit 就在那里结束程序并进行一些清理。清理包括销毁具有静态存储持续时间的对象,但不包括具有自动存储持续时间的对象,这些对象通常会在离开范围时被销毁。

在你的例子 B b; 中,包括它存储的所有元素,通常会在 main}return 语句中销毁,但是因为你调用exit 事先,它永远不会被摧毁。在这种特殊情况下这不是问题,但如果例如b 是一个带有析构函数的对象,它应该执行一些在程序外可见副作用的操作,它可能是。

您不应调用 exit(0)main 退出程序。只需使用 return 0; 或完全不使用它,因为对于 main 具体而言,没有 return 语句等同于 return 0;.


旁注:您不应该显式 declare/define 不执行任何操作且不是 virtual 的析构函数,例如 A::~A() {}。如果您根本没有在 class 中声明析构函数,编译器将自动为您生成它,并且其行为完全相同。

无论如何手动声明析构函数都会对其他特殊成员函数的隐式生成产生影响,这可能会影响程序的性能,并且还会使始终遵循 rule of 0/3/5.


My first question is that the object A(v) that added the the map, it should be deleted automatically when exit the scope?

A(v) 是临时对象,将在完整表达式 a_[name] = A(v).

结束时销毁

Also, do I need to provide a copy constructor?

不,如果您不手动声明一个(与析构函数相同),编译器会隐式声明一个,并且假设这是可能的,它将被定义为简单地复制每个成员。这通常是您想要的。

My last question is that I did not create any object with "new", I shouldn't need to delete any.

是的,完全正确。