我遇到内存泄漏问题。我有一个基类指针。从中,我使用new
来分配不同的派生类。然后,当我尝试delete
带引用的类(不是类型转换)时,我得到内存泄漏。我研究了这个问题,发现我应该在基类中添加一个虚拟析构函数,但是我尝试了这个并且仍然有内存泄漏;也就是说,根据我的任务管理器,使用基类指针每次分配和删除派生类时,内存使用量会继续增加。我试图使它成为一个抽象的析构函数,并在派生类中添加了析构函数,但是我得到了一个未定义的引用错误。我还尝试将指针类型转换为delete
的派生类指针,但显然这会使程序崩溃。
有谁知道我应该怎么做?
示例代码:
class A {
public:
A();
~A() {};
virtual ~A(); /*or*/
virtual ~A()=0; /*or*/
/*or nothing?*/
}
class B: private A {
public:
B();
~B() {}; /*this?*/
/*or nothing?*/
}
答案 0 :(得分:5)
你确定内存泄漏有多确定?通常,任务管理器在这里没有太大帮助,因为它无法分辨出实际分配了多少属于您的进程的内存。即使释放的内存仍然属于您的进程,并且可能在以后由内存管理(通常类似malloc的系统库)使用。
使用诸如mallocdebug,valgrind,purify等工具来查明是否存在内存泄漏。这些工具将用一个新工具替换malloc实现,该工具跟踪已分配的内存并报告在进程终止时未释放的内存。
注意:在大多数系统上,在进程退出之前,从进程中释放的内存不会返回到系统。但是,它可以在同一个过程中进行新的分配。
答案 1 :(得分:3)
如果你有一个虚拟析构函数,你的子类的析构函数都将被调用。不需要用抽象的解构器或任何东西做任何神秘的魔法。
我认为内存泄漏位于对象内部。也许你在B(或A的?)构造函数中调用new()
,但你不删除它。没有看到更多的代码,我只能说“你的析构函数设置很好”。
答案 2 :(得分:3)
使用virtual ~A();
如果允许virtual ~A()=0
,我会感到惊讶。
使用此代码:
A* base = new B();
delete base;
B的析构函数然后将被调用。
如果你真的还在泄漏记忆,那么你在其他地方又有另一个泄漏。
答案 3 :(得分:0)
您可以使用:
virtual ~A(){}
或
virtual ~A()=0;
// as long as there is also:
A::~A(){} // inline in the header file or non-inline in the cpp file.
这意味着:
A* base;
...
delete base;
将以正确的顺序调用派生类的所有析构函数。
请注意,如果在没有其他成员函数是纯虚拟的情况下需要拥有抽象基类时,纯虚拟析构函数virtual ~A()=0;
会很有用。