0

With a base class Heap and two derived classes MinHeap and MaxHeap - shown below:

I create a derived class object as :

MinHeap* myminheap = new MinHeap();

but deleting it using

delete myminheap;

with/without virtual ~Heap() {} gives me glibc memory leak error ! what is the crux? I have gone thru a lot of posts on this .....

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

.... but I am not able to figure why setting the base destructor virtual still causes memory error?

Heap* h_ptr = myminheap;
delete h_ptr;

ps. Doing the ^ thing is not possible, I cannot typecast the derived class object pointer to base pointer as the following errors pop up

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

which I can take care by introducing them in the Heap class

Later, I have realised that instead of calling delete h_ptr; if I call free(h_ptr); I am not subjected to the memory leaks .. Hurray ! But I need some light shed on this behaviour !

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;
}
Community
  • 1
  • 1
Sunil Kundal
  • 143
  • 1
  • 2
  • 8

1 Answers1

0

If you new a MinHeap, you cannot then delete it by calling free on a Heap type. Your problem is that you are storing a pointer to the object and saying it is a different thing, as a result the delete routine doesn't know that you're trying to delete a MinHeap, and only deletes the Heap part (roughly).

you can call delete on the myminheap object directly, that should work.

A better solution is not to create a MinHeap on the heap at all, create it on the stack and use it without any pointers. If you needed to create it on the heap for some reason, create it inside a smart pointer class instead, like use shared_ptr<> which will help you immensely.

gbjbaanb
  • 51,617
  • 12
  • 104
  • 148
  • The complete code does not show that but then the first time it showed a `new` followed by a `free` so it is not clear to me this is the same code that crashes. – Shafik Yaghmour Apr 10 '13 at 09:21
  • @ShafikYaghmour `new` was first followed by `delete` as it is shown in updated post now with `new` followed by `free` no error pops up .. note: the `free` modification which I tried is mentioned before the complete code above – Sunil Kundal Apr 10 '13 at 09:28