0

My program is simple, make a tree (min heap), and through a inorder traversal to store data to an array, then destroy the tree (heap).

When I run to the store step, the program crash. I can't find why, even I know the bug position (I comment some code and run to see whether it works and finally I find the bug position)

I think maybe I delete a invalid pointer, but I can't find where; please help me to find it.

When I input

6
1 2 3 4 5 6

it works when I input

8
90 80 30 40 10 45 20 50

then crash.

I don't know what different between this two group numbers

#include <iostream>

typedef int ElementType;

struct BTree
{
    ElementType data;
    BTree *Left;
    BTree *Right;
};

class BuildingMinHeap
{
    ElementType *Elements;
    int Size;
    int Capacity;
    BTree *root;
    ElementType *inorder_array; // to store members inorderly

public:
    BuildingMinHeap(int MaxSize, ElementType MinData): Size(0), Capacity(MaxSize+1)
    {
        Elements = new ElementType[MaxSize+1];
        Elements[0] = MinData;  // sentinel
        root = NULL;
        inorder_array = new ElementType[Size];  
    }

    ~BuildingMinHeap()
    {
       if (Elements)
           delete [] Elements;
       if (inorder_array)
           delete [] inorder_array;
       if (root != NULL)
           DeleteBTree(root);
    }

    void Insert(ElementType item);

    void genBTree(ElementType *a, int position);    // call CreateBTree()

    void ModifyArray(ElementType *input, int size); // call gen_inorder_array()


    ElementType *getElements()  {return Elements;}
    BTree *getRoot()    {return root;}
    void DeleteBTree(BTree *root);


private:
    BTree *CreateBTree(ElementType *a, int position);
    void gen_inorder_array(const BTree *node);
};

void BuildingMinHeap::Insert(ElementType item)
{
    int i;

    i = ++Size;
    for (; Elements[i/2] > item; i /= 2)
    {
        // Elements[0] is sentinel
        Elements[i] = Elements[i/2];
    }
    Elements[i] = item;
}

BTree *BuildingMinHeap::CreateBTree(ElementType *a, int position)   // array to Binary Tree list
{
    BTree *new_node = new BTree;
    if (position > Size)
        return NULL;

    new_node->data = a[position];
    new_node->Left = CreateBTree(a, 2*position);
    new_node->Right = CreateBTree(a, 2*position+1);

    return new_node;

}

void BuildingMinHeap::genBTree(ElementType *a, int position)    // call CreateBTree()
{
    root = CreateBTree(a, position);
}

void BuildingMinHeap::DeleteBTree(BTree *root)
{
    if (root == NULL)
        return;
    DeleteBTree(root->Left);
    DeleteBTree(root->Right);
    delete root;
    root = NULL;
    return;
}

void BuildingMinHeap::gen_inorder_array(const BTree *node)   // to generate members of tree root inorderly
{
    static int index = 0;
    // like print inorder tree
    if (node)
    {
        gen_inorder_array(node->Left);
        inorder_array[index++] = node->data;
//        std::cout << node->data << " ";
        gen_inorder_array(node->Right);
    }
}


void BuildingMinHeap::ModifyArray(int *input, int size) // call gen_inorder_array()
{

    gen_inorder_array(root); // generate inorder_array, when I comment this line, it work
    // below commented code is nothing about tree root member

//
//    // generate<elements of inorder_array,elements' address of Elements> map
//    std::map<int, int*> inorder_Ele_map;
//    for (int i = 0; i != Size; i++)
//    {
//        ElementType *it = std::find(Elements+1, Elements+Size, *(inorder_array+i));
//        inorder_Ele_map[*(inorder_array+i)] = Elements + (it-Elements);
//    }
//    
//
//    // change Elements array according input array
//    for (int i = 0; i != size; i++)
//    {
//        if (*(inorder_array+i) != *(input+i))
//        {
//            *(inorder_Ele_map[*(inorder_array+i)]) = *(input+i);
//        }
//    }
}




int main(void)
{
    int n;
    std::cin >> n;
    int *input = new int[n];
    for (int i = 0; i != n; i++)
        std::cin >> input[i];

    BuildingMinHeap h(n, -999); // empty heap;
    for (int i = 0; i != n; i++)
        h.Insert(input[i]); // insert element to heap

    h.genBTree(h.getElements(), 1); // generate Binary Tree(pointer) from Elements array, index 1 begin
    // so far it work
    h.ModifyArray(input, n);    // if I comment this line, it would work
    h.DeleteBTree(h.getRoot()); // I have already do call this function in destructor, 
                                // but in destructor I call it when root != NULL, 
                                // I have no idea when I comment this line, there are a crash.

    delete [] input;

    return 0;
}
halfer
  • 19,824
  • 17
  • 99
  • 186
  • 1
    Use valgrind and your debugger. – asu Oct 22 '16 at 08:10
  • @WhozCraig, `-999`is `Size`, and `size` just a length of array – user6778787 Oct 22 '16 at 08:14
  • Ok. Got it. Thanks. – WhozCraig Oct 22 '16 at 08:15
  • @Asu I use gdb, and I think gdb not given a detail error message, I'll try valgrind – user6778787 Oct 22 '16 at 08:16
  • Compile in `-O0 -g` and try again. Run it with `gdb`, and when the segfault occurs you should get a gdb prompt. IIRC it may also show the line where the crash happened, if it could be found. Then use `bt full` and you can examine the stack trace. – asu Oct 22 '16 at 08:34
  • @Asu thanks, it's complicated, I must study for a while – user6778787 Oct 22 '16 at 08:45
  • 1
    Think about the size of `inorder_array` until you see what the problem is. – molbdnilo Oct 22 '16 at 08:48
  • @molbdnilo yeah, I just ran across that as well. nice catch. – WhozCraig Oct 22 '16 at 08:52
  • @molbdnilo thanks, I new a int[0]. But Why I input the data like group 1, it works, maybe I accidentally access the unknow memory and that is valid? – user6778787 Oct 22 '16 at 09:03
  • "it works" - it *doesn't*. You were (un)lucky to be lulled into a false sense that it *does*. By undersizing that array (and thus later breaching it) your program invokes *undefined behavior*. As such, there is no longer any point in trying to find definition of sense where there is none. Don't confuse *observed* behavior with *defined* behavior. Once you invoke undefined behavior, anything can happen, including the appearance that everything is ok (and making for rather pesky bugs and embarrassing moments when submitting code to instructors, or worse, *customers*). – WhozCraig Oct 22 '16 at 09:08
  • @WhozCraig yeah, you're right. – user6778787 Oct 22 '16 at 09:31

0 Answers0