2013-04-10 39 views
0

與鹼類Heap和兩個派生類MinHeapMaxHeap - 如下所示:在什麼情況下,虛擬基礎析構函數仍可能導致內存泄漏而不被調用?

我作爲創建派生類對象:

MinHeap* myminheap = new MinHeap(); 

但刪除它使用

delete myminheap; 

與/沒有virtual ~Heap() {}給我glibc內存泄漏錯誤! 什麼是關鍵? 我已經通了很多關於這個職位的.....

Overriding operator new/delete in derived class

Why base class destructor (virtual) is called when a derived class object is deleted?

memory leak when deleting derived class with base-class pointer

....但我無法弄清楚,爲什麼設置基地析構函數虛仍然會導致內存錯誤?

Heap* h_ptr = myminheap; 
delete h_ptr; 

ps。在做^事情是不可能的,我不能強制轉換派生類對象指針的基礎指針下面的錯誤彈出

‘class Heap’ has no member named ‘insert’ 
‘class Heap’ has no member named ‘pop_min' 

,我可以通過在Heap

後來引進他們照顧,我已經意識到,如果我打電話給delete h_ptr;,而不是撥打free(h_ptr);,我不會遭受內存泄漏。 萬歲!但是我需要一些關於這種行爲的燈光!

heap.h

#include <cstdlib> 
#include <vector> 
#include <iterator> 

using namespace std; 

class Heap 
{ 
    public: 
    Heap() {} 
    ~Heap() {} 

    vector <int> heap; 
    int left(int parent); 
    int right(int parent); 
    int parent(int child); 
    int size()     {return heap.size();} 
    virtual void insert(int element) {} 
    virtual int pop_min() {} 
    virtual int pop_max() {} 
    void print(); 
}; 

class MinHeap : public Heap 
{ 
    private: 
    void heapify_up(int index); 
    void heapify_down(int index); 

    public: 
    MinHeap() {} 
    ~MinHeap() {} 

    int pop_min(); 
    void insert(int element); 
}; 

class MaxHeap : public Heap 
{ 
    private: 
    void heapify_up(int index); 
    void heapify_down(int index); 

    public: 
    MaxHeap() {} 
    ~MaxHeap() {} 

    int pop_max(); 
    void insert(int element); 
}; 

heap.cc

#include <cstdlib> 
#include <iostream> 
#include <vector> 
#include <iterator> 

using namespace std; 

#include "heap.h" 

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
int Heap::left(int parent) 
{ 
    int i = (parent << 1) + 1; //2 * parent + 1 read more on bit shifts 
    return (i < heap.size()) ? i : -1; 
} 

int Heap::right(int parent) 
{ 
    int i = (parent << 1) + 2; 
    return (i < heap.size()) ? i : -1; 
} 

int Heap::parent(int child) 
{ 
    if(child){ 
     int i = (child >> 1) - 1; 
     return i; 
    } 
    else return -1; 
} 

void Heap::print() 
{ 
    vector<int>::iterator i = heap.begin(); 
    cout << "Heap = "; 
    while(i != heap.end()){ 
     cout << *i << " "; 
     i++; 
    } 
    cout << endl; 
} 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
int MinHeap::pop_min() 
{ 
    int min = heap.front(); 
    heap[0] = heap[heap.size() - 1]; 
    heap.pop_back(); 
    heapify_down(0); 
    return min; 
} 

void MinHeap::insert(int element) 
{ 
    heap.push_back(element); 
    heapify_up(heap.size() - 1); 
} 

void MinHeap::heapify_up(int index) 
{ 
    while(index > 0 && parent(index) >= 0 && heap[parent(index)] > heap[index]){ 
     int temp = heap[index]; 
     heap[index] = heap[parent(index)]; 
     heap[parent(index)] = temp; 
     index = parent(index); 
    } 
} 

void MinHeap::heapify_down(int index) 
{ 
    int child = left(index); 

    if(child > 0 && right(index) > 0 && heap[child] > heap[right(index)]) 
     child = right(index); 

    if(heap[index] > heap[child]){ 
     int temp = heap[child]; 
     heap[child] = heap[index]; 
     heap[index] = temp; 
     heapify_down(child); 
    } 
} 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
int MaxHeap::pop_max() 
{ 
    int max = heap.front(); 
    heap[0] = heap[heap.size() - 1]; 
    heap.pop_back(); 
    heapify_down(0); 
    return max; 
} 

void MaxHeap::insert(int element) 
{ 
    heap.push_back(element); 
    heapify_up(heap.size() - 1); 
} 

void MaxHeap::heapify_up(int index) 
{ 
    while(index > 0 && parent(index) >= 0 && heap[parent(index)] < heap[index]){ 
     int temp = heap[index]; 
     heap[index] = heap[parent(index)]; 
     heap[parent(index)] = temp; 
     index = parent(index); 
    } 
} 

void MaxHeap::heapify_down(int index) 
{ 
    int child = left(index); 

    if(child > 0 && right(index) > 0 && child < right(index)) 
     child = right(index); 

    if(heap[index] < heap[child]){ 
     int temp = heap[child]; 
     heap[child] = heap[index]; 
     heap[child] = temp; 
     heapify_down(child); 
    } 
} 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
//    test program 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
int main(){ 
    // Create the heap 
    MinHeap* myminheap = new MinHeap(); 
    myminheap->insert(700); 
    myminheap->print(); 
    myminheap->insert(500); 
    myminheap->print(); 
    myminheap->insert(100); 
    myminheap->print(); 
    myminheap->insert(800); 
    myminheap->print(); 
    myminheap->insert(200); 
    myminheap->print(); 
    myminheap->insert(400); 
    myminheap->print(); 
    myminheap->insert(900); 
    myminheap->print(); 
    myminheap->insert(1000); 
    myminheap->print(); 
    myminheap->insert(300); 
    myminheap->print(); 
    myminheap->insert(600); 
    myminheap->print(); 

    // Get priority element from the heap 
    int heapSize = myminheap->size(); 
    for (int i = 0; i < heapSize; i++) 
     cout << "Get min element = " << myminheap->pop_min() << endl; 

    // Cleanup 
    delete myminheap; 

    return 1; 
} 
+4

您不得混用'new'和'free'。這段代碼看起來非常好。你如何使用它?什麼是確切的錯誤信息(或者是什麼讓你思考,如果沒有這樣的信息就有泄漏)? – 2013-04-10 09:01:58

+2

總是調用虛擬析構函數。你的問題在別處。發佈一個完整的例子來重現錯誤。 – 2013-04-10 09:02:26

+0

這並不意味着內存泄漏。發佈代碼,顯示你如何使用這個類。 – 2013-04-10 09:07:14

回答

0

如果新一MinHeap,你不能再通過調用免費堆型將其刪除。你的問題是你正在存儲一個指向這個對象的指針,並且說它是一個不同的東西,因此刪除例程並不知道你試圖刪除一個MinHeap,而只是刪除了Heap部分(粗略地)。

你可以直接調用myminheap對象上的刪除操作。

一個更好的解決方案不是在堆上創建MinHeap,而是在堆棧上創建它,並在沒有任何指針的情況下使用它。如果因爲某種原因需要在堆上創建它,請在智能指針類中創建它,而不是像shared_ptr這樣可以幫助你。

+0

完整的代碼沒有顯示,但然後第一次顯示一個「新」,後面跟着一個「免費」,所以我不清楚這是與崩潰相同的代碼。 – 2013-04-10 09:21:39

+0

@ShafikYaghmour'new'首先跟着'delete',因爲它在更新後的帖子中現在顯示爲 ,'new'後面跟''free'沒有彈出錯誤.. 注:我試過的免費修改被提及在上面的完整代碼之前 – 2013-04-10 09:28:12

相關問題