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

ccp*_*lus 2 c++ valgrind memory-leaks object

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

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

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

我的最后一个问题是,我没有使用“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);
}
Run Code Online (Sandbox Code Playgroud)

瓦尔格林德

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)
Run Code Online (Sandbox Code Playgroud)

use*_*522 5

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

==xxxx==    still reachable: 72 bytes in 1 blocks
Run Code Online (Sandbox Code Playgroud)

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

但是,这仍然可能是问题的征兆,例如,如果应该被销毁且具有带副作用的析构函数的对象未运行。

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

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

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


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

无论如何,手动声明析构函数都会对特殊成员函数的其他隐式生成产生影响,这可能会影响程序的性能,并且也使得一致遵循0/3/5 规则变得更加困难。


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

A(v)是一个临时对象,将在完整表达式结束时被销毁a_[name] = A(v)

另外,我需要提供复制构造函数吗?

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

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

是的,这是完全正确的。