Thread: Binary Tree Heap Destructor failing

  1. #1
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499

    Binary Tree Heap Destructor failing

    I get a runtime error when I add a destructor to my code.

    Code:
    #include <iostream>
    #include <array>
    
    using namespace std;
    
    struct nodes {  int* elements; };
    
    class heap
    {
    private:
        int length;
        nodes item;
        
    public:
        heap();
        //~heap();
        void heap_size(int num);
        void push_heap(int item);
        void maxHeapify(int parent,int last);
        void print_heap();
    };
    
    heap::heap() { }
    
    /*heap::~heap()
    {
        delete [] item.elements;
    }*/
    
    //setting size of the array and making a new one
    void heap::heap_size(int max)
    {
        item.elements = new int [max];
    }
    
    //pushing numbers into the array
    void heap::push_heap(int number)
    {
        length++;
        item.elements[length-1] = number;
    }
    
    //sorting the array
    void heap::maxHeapify(int parent, int last)
    {
        int child = 2 * parent;
        while (child <= last)
        {
            if (child + 1 <= last && item.elements[child+1] > item.elements[child])
                child++;
            
            if (item.elements[child] > item.elements[parent])
            
                swap(item.elements[child], item.elements[parent]);
            
            parent = child;
            child = 2*parent;
            
        }
    
    }
    
    void heap::print_heap()
    {
        
        for (int i=0; i<length; ++i)
        {
            cout<<"element["<<i<<"]"<<item.elements[i]<<",";
        }
    }
    
    int main(int argc, const char * argv[])
    {
        
        
        cout<<"How many numbers do you want to enter into the heap?"<<endl;
        int amount;
        cin>>amount;
        
        heap myHeap;
        myHeap.heap_size(amount); //setting the size of the array
        
        int numbers=0;
        cout<<"Enter "<<amount<<" numbers into the heap and press enter to see the results printed."<<endl;
        
        for (int i=1; i<=amount; ++i)
        {
            cin>>numbers;
           myHeap.push_heap(numbers); //push numbers into the array
        }
        
        myHeap.maxHeapify(0, amount);
        
        myHeap.print_heap();
        
       // myHeap.~heap();
        
        
        return 0;
    }

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    I get a runtime error when I add a destructor to my code.
    Do you mean that you get a runtime error when you add the destructor code?

    Or do you mean when you try to call the destructor?

    Jim

  3. #3
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    Sorry...Runtime error

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    length is never initialized, so you probably write off the end of the array.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Again:
    Do you mean that you get a runtime error when you add the destructor code?

    Or do you mean when you try to call the destructor?
    Please answer the above questions.

    Also run the program through your debugger, the debugger should tell you exactly where it encounters the problem.

    By the way you probably shouldn't be calling your destructor and you probably should have a check in your destructor insuring there are items that need to be deleted.

    Jim

  6. #6
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    When I call my destructor it reads:

    Binary Tree Heap(988,0x7fff784cd310) malloc: *** error for object 0x100000000: pointer being freed was not allocated
    *** set a breakpoint in malloc_error_break to debug
    element[0]4,element[1]5,element[2]3,element[3]2,element[4]6


    By the way you probably shouldn't be calling your destructor and you probably should have a check in your destructor insuring there are items that need to be deleted.
    I thought if you have a pointer in a class or struct you need to free it when you are not using it anymore.





  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by jocdrew21
    I thought if you have a pointer in a class or struct you need to free it when you are not using it anymore.
    If the pointer points to a resource that needs to be released, sure. But that would be done in the destructor (which you commented out), which is then automatically called in this case. You don't actually need to check in the destructor if you had initialised the pointer member in the item struct to be a null pointer. std::vector<int> would likely be a better alternative.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Here is some revised code that adds checks to ensure you aren't doing bad stuff.
    Note that I initialized length (which I told you that you didn't - that's undefined behaviour right there!) and I only made is so you can determine the size when first constructing the heap as otherwise you would get memory leaks if setting the size more than once.
    Code:
    struct nodes { int* elements; };
    
    class heap
    {
    private:
    	int length;
    	int elements;
    	nodes item;
    
    	void heap_size(int num);
    
    public:
    	heap(int elements);
    	~heap();
    	void push_heap(int item);
    	void maxHeapify(int parent, int last);
    	void print_heap();
    };
    
    heap::heap(int elements): length(0)
    {
    	assert(elements >= 0);
    	heap_size(elements);
    }
    
    heap::~heap()
    {
    	delete [] item.elements;
    }
    
    //setting size of the array and making a new one
    void heap::heap_size(int max)
    {
    	item.elements = new int[max];
    	elements = max;
    }
    
    //pushing numbers into the array
    void heap::push_heap(int number)
    {
    	length++;
    	item.elements[length - 1] = number;
    }
    
    //sorting the array
    void heap::maxHeapify(int parent, int last)
    {
    	assert(parent < elements);
    	assert(last < elements);
    	assert(parent >= 0);
    	assert(last >= 0);
    	
    	int child = 2 * parent;
    	assert(child < elements);
    	assert(child >= 0);
    
    	while (child <= last)
    	{
    		assert(child < elements);
    		assert(child >= 0);
    		assert(parent < elements);
    		assert(parent >= 0);
    		assert(last >= 0);
    		assert(last < elements);
    		if (child + 1 <= last)
    		{
    			assert(child < elements);
    			assert(child >= 0);
    			assert(child + 1 < elements);
    			assert(child + 1 >= 0);
    			if (item.elements[child + 1] > item.elements[child])
    				child++;
    			assert(child < elements);
    			assert(child >= 0);
    		}
    
    		assert(child < elements);
    		assert(child >= 0);
    		assert(parent < elements);
    		assert(parent >= 0);
    		if (item.elements[child] > item.elements[parent])
    			swap(item.elements[child], item.elements[parent]);
    
    		parent = child;
    		child = 2 * parent;
    	}
    }
    
    void heap::print_heap()
    {
    	for (int i = 0; i < length; ++i)
    	{
    		cout << "element[" << i << "]" << item.elements[i] << ",";
    	}
    }
    
    int main(int argc, const char * argv[])
    {
    	cout << "How many numbers do you want to enter into the heap?" << endl;
    	int amount;
    	cin >> amount;
    
    	heap myHeap(amount);
    	int numbers = 0;
    	cout << "Enter " << amount << " numbers into the heap and press enter to see the results printed." << endl;
    
    	for (int i = 1; i <= amount; ++i)
    	{
    		cin >> numbers;
    		myHeap.push_heap(numbers); //push numbers into the array
    	}
    
    	myHeap.maxHeapify(0, amount - 1);
    	myHeap.print_heap();
    	return 0;
    }
    This runs, at least for me. I will not vouch for its correctness.
    Again, though, you are better off using std::vector.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    assert, never seen this before. I just read about it on cplusplus.com and from what I can gather is this used for debugging.
    Why would a vector be better? Is it because with can use my vector.at(*it) or is there another reason?

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    vector is better because it manages memory for you and can do bounds checking which can be used as a debug aid.
    It also has other functionality that can aid programming. You can read all about it at cplusplus.com.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    Code:
    struct nodes {  int* elements;};
    
    class heap
    {
    private:
        int length;
        nodes item;
        
    public:
        heap();
        heap(int);
        ~heap();
        void heap_size(int num);
        void push_heap(int item);
        void maxHeapify(int parent,int last);
        void print_heap();
    };
    
    heap::heap() { length = 0; item.elements=NULL; }
    
    heap::heap(int l) :length(l) { }
    
    heap::~heap()
    {
        delete [] item.elements;
    }
    This runs, at least for me. I will not vouch for its correctness.
    Again, though, you are better off using std::vector.
    assert gave me a few issues not but I didn't use it in my functions just in the constructor like you. I forgot to add my code earlier.

  12. #12
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    Thank you everyone for the help. I can see why a vector is better.

    Is there a library for this?

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by jocdrew21
    Is there a library for this?
    The standard header <algorithm> makes available several operations for heaps. In particular, with make_heap, you can turn a range with random access (e.g., the entire range of a std::vector) into a heap.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    There is also std::map, std::unordered_map and std::set, depending on your requirements.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    I have been reading about these and they are awesome.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Converting From Binary Tree to Threaded Binary Trees
    By elton_fan in forum C Programming
    Replies: 15
    Last Post: 11-08-2007, 11:41 PM
  2. Replies: 2
    Last Post: 08-01-2007, 01:08 PM
  3. Replies: 0
    Last Post: 11-04-2006, 11:07 AM
  4. binary heap (build question)
    By axon in forum C++ Programming
    Replies: 1
    Last Post: 03-01-2004, 10:49 PM
  5. display tree data in binary tree format
    By xddxogm3 in forum C++ Programming
    Replies: 4
    Last Post: 12-11-2003, 12:47 AM