2011-03-03 111 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;會很有用。