2011-03-03 113 views
4

我遇到内存泄漏问题。我有一个基类指针。从它,我使用new分配不同的派生类。然后,当我尝试delete这些类与参考(没有typecasted),我得到一个内存泄漏。我研究了这个问题,发现我应该向基类添加一个虚拟析构函数,但是我尝试了这个,并且仍然有内存泄漏;也就是说,根据我的任务管理器,使用基类指针进行派生类的每次分配和删除时,内存使用率会持续上升。我试着将它作为一个抽象析构函数并向派生类中添加了析构函数,但是我得到了一个未定义的引用错误。我也试着将指针作为delete的派生类指针进行类型化,但显然这会导致程序崩溃。使用基类指针删除派生类时的内存泄漏

有没有人有任何想法我应该做什么?

示例代码:

​​
+0

组合是使用私有继承的一个很好的选择(http://www.parashift.com/c++-faq-lite/private-inheritance.html#faq-24.3) – James 2011-03-03 21:38:51

回答

3

使用virtual ~A();

如果virtual ~A()=0允许我会感到惊讶。

有了这个代码:

A* base = new B(); 
delete base; 

对于B析构函数然后将被调用。

如果你真的仍然在泄漏记忆,那么你在别处有另一个泄漏。

+0

惊喜,惊喜。它是。 – Axel 2011-03-03 21:42:36

+0

+1让自己兴奋。哦,感谢'标准'。 – 2012-09-29 11:30:59

+0

纯虚拟析构函数在C++中是合法的,无论如何你必须为它提供一个实现: 'struct A {virtual〜A()= 0};' 'A ::〜A(){}' pure virtual dtor当你想要一个抽象的基类时是很有用的,但是dtor是它唯一的虚拟方法 – thrantir 2014-07-23 07:59:05

3

如果你有一个虚析构函数,你的子类中的析构函数(或多个)都将被调用。不需要用抽象的解构器或任何东西来做任何深奥的魔法。

我会假设内存泄漏是在你的对象内的某个地方。也许你在B的(或A的?)构造函数中调用new(),但是你不要删除它。没有看到更多的代码,我只能说“你的析构设置很好”。

+0

等待 - 哪个解构器安装程序? – Codesmith 2011-03-03 21:53:38

+1

只需'virtual〜A()'。 – EboMike 2011-03-03 21:54:04

5

你有多确信真的有内存泄漏?通常情况下,任务管理器在这里没有多大帮助,因为它不能分辨出实际分配了多少属于你的进程的内存。即使被释放的内存仍然属于你的进程,并且可能在以后被内存管理使用(通常是malloc-like系统库)。

使用诸如mallocdebug,valgrind,purify等工具来确定是否确实存在内存泄漏。这些工具将用一个新的malloc实现来替代malloc实现,该实例跟踪分配的内存并报告进程终止时未释放的内存。

注意:在大多数系统上,从进程中释放的内存在进程退出之前不会返回到系统。不过,它可以在同一个过程中进行新的分配。

+0

+1可能可以节省AUTO在有人给我提供这个线索之前,我经历了不必要的痛苦。 – ceo 2011-03-03 22:43:45

+0

也许,但任务管理器似乎只显示内存增加缓慢 - 但它不会泄漏? – Codesmith 2011-03-03 23:57:57

+1

+1任务管理器在于。大多。使用一个真正的调试工具,而不是尝试使用未对准双筒望远镜测量一英里外的蚁丘的高度。 – 2011-03-04 03:55:58

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;会很有用。