-1

I was experimenting a little bit with C++ and decided to try and create whole tree deletion method for Binary Tree. For some reason I keep getting pointer error because pointer is 0xDDDDDDDD.

If someone can explain me why it does not work I would appreciate it so I can learn more about pointers.

struct Node {
    Node*  parent;
    Node *left,
         *right;
    int value;


   inline Node() : parent(nullptr), left(nullptr), right(nullptr), value(0){}

   ~Node() = default;

};

class BST {
public:
    Node* root;

    
public:
    BST() = default;
    inline BST(int i)
    {
        root = new Node();
        root->value = i;
        root->parent = nullptr;
        root->left = nullptr;
        root->right = nullptr;
    }
    BST(const BST& bst) = default;
   

    void Insert(int i);
    void DeleteAll(Node* node);


};

#include <iostream>

int main()
{
    BST t(20);
    t.root->left = new Node();
    t.root->left->value = 22;
    t.root->left->parent = t.root;

    t.root->right = new Node();
    t.root->right->value = 15;
    t.root->right->parent = t.root;



  


    t.DeleteAll(t.root);
    
}


void BST::Insert(int i)
{
   

}



void BST::DeleteAll(Node* node)
{ 
 
    Node* target = node;

    std::cout << "Probing node with value " << node->value << std::endl;


    if (node->left == nullptr && node->right == nullptr)
    {
        target = node->parent;  
        std::cout << "Node deleted with value: " << node->value << std::endl;     
        delete node;    

        if (target == nullptr)
        {
            std::cout << "Found and deleted root!" << std::endl;
            return;
        }

        std::cout << "Parents node value: " << target->value << std::endl;     
    }

    else if (node->left != nullptr)
    {
        std::cout << "Found left ptr with value: " << node->left->value << std::endl;
        target = node->left;

    }
    else if(node->right != nullptr)
    {
        std::cout << "Found right ptr with value: " << node->right->value << std::endl;
        target = node->right; 
    }

    DeleteAll(target);

}

The prompt from the console I am getting is:

Probing node with value 20
Found left ptr with value: 22
Probing node with value 22
Node deleted with value: 22
Parents node value: 20
Probing node with value 20
Found left ptr with value: -572662307
Probing node with value -572662307

In DeleteAll() function when it gets back to parent node to search if there is any children that is not null it always finds the left child which I deleted before. Shouldn't it be null?

And there it crashes. I have no idea why is it doing that but something is probably in the delete function. This is not a homework of any kind I am just trying to learn why this does not work.

273K
  • 29,503
  • 10
  • 41
  • 64
GoldSpark
  • 69
  • 7
  • 1
    You have two nodes with the same parent and you delete parent twice. – 273K Nov 12 '21 at 02:18
  • *This is not a homework of any kind* -- Sorry, but why is that relevant? Homework or no homework, the effort required on the poster to debug the code is the same. – PaulMcKenzie Nov 12 '21 at 02:19
  • 1
    `0xDDDDDDDD` is a magic debug code. Related: [https://stackoverflow.com/questions/127386/in-visual-studio-c-what-are-the-memory-allocation-representations](https://stackoverflow.com/questions/127386/in-visual-studio-c-what-are-the-memory-allocation-representations) – drescherjm Nov 12 '21 at 02:39
  • @S.M. I must be blind or something hahah... How if it gets deleted it would say in console because the only delete operator is in that *if* conditional where there is std::cout. It would say deleting node with value 20(parent of both left and right) . It deletes left node and then again it says left node is not nullptr but that magic debug code. I dont know I cant see it. You probably are right I just cant see it – GoldSpark Nov 12 '21 at 14:10

1 Answers1

2

When I run your code I get this output, and it throws "read access violation":

Found left ptr with value: -572662307

-572662307 is same as 0xDDDDDDDD This is specific for Visual Studio in debug mode. Sometimes you may not get this value.

The problem is you never allocated memory for parent (which you don't even need, more on that later) then you try to delete it over and over.

You should rewrite you code like this to understand it better:

void DeleteAll(Node* node)
{
    printf("node: %p\n", node);
    Node* target = node;
    if (!node->left && !node->right)
    {
        target = node->parent; //this was never allocated, supposed to be NULL
        delete node; 
        if (target == nullptr) //target is now undefined, not NULL, can't be tested
            return; //we may not get here
    }
    else if (node->left != nullptr)
        target = node->left;
    else if (node->right != nullptr)
        target = node->right;

    DeleteAll(target); //could be deleting the same thing again
}

The output is something like this, with different numbers:

node: 012C5078
node: 012D2F00
node: 012C5078
node: 012D2F00
node: DDDDDDDD

You see the same values repeated, it's trying to delete twice. The correct DeleteAll function is just this:

void BST::DeleteAll(Node* node)
{
    if (!node)
        return;
    DeleteAll(node->left);
    DeleteAll(node->right);
    delete node;
}

You will also need a different Delete(Node* node, int value) function which deletes based on value,left,right, this will be used once you properly insert items, and you want to remove some values before BST is destroyed.

Try this example instead:

https://gist.github.com/harish-r/a7df7ce576dda35c9660

Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • Thanks for the answer. I know that technique of node deletion I was just experimenting with the one I wrote because I wanted to have a pointer to a parent node for some testing and playing with the code. You said I did not allocate parents memory. It is allocated in BST constructor. Lefts and rights parent is the root node from BST constructor. I thought deleting allocated memory will automatically set it to nullptr? – GoldSpark Nov 12 '21 at 14:07
  • See updated answer. You can put `printf("target: %p\n", target);` before and after `delete node;` to see better what it's doing. By the way, if you run this in Release mode, VS is not going put `0xDDDDDDDD` in there, it leads to endless recursion until it runs of stack memory. – Barmak Shemirani Nov 12 '21 at 14:32
  • For some reason it is still checking roots left child again even after delete. I am so confused I apologize. It is probably something so simple I can't see it... ahah omg. You said in comment "target is now undefined, NOT NULL, cant be tested" but after putting *print()* to check value of target it shows root node's value correctly which is a parent of the node that has been deleted. Then it goes to check if root again has some child and again it finds left child even if it is deleted. – GoldSpark Nov 12 '21 at 14:42
  • Found out just now even though you said it in the comment of the code that deleting a pointer does not make it NULL value... Have to think of some other approach to this. Thank you. – GoldSpark Nov 12 '21 at 21:12
  • 1
    I posted a second `DeleteAll` method which should work with your code. In VS you can also use `_CrtDumpMemoryLeaks()` to check for leaks. Note that other BST classes have a `Delete` method similar to you posted, but that's not for cleanup, it is used to remove a value and free its nodes. `Delete` in those classes is basically the opposite of `Insert` (which you have not implemented, or haven't shown) – Barmak Shemirani Nov 12 '21 at 21:36
  • I know for the second method and it does work. I used it before for BST this was just some practice with pointers so I made things more complicated for me for purpose. Right now I did the problem without recursion in a while loop. Thank you once more for your help! You helped me greatly by refreshing my memory of pointers not resetting variable to NULL after delete. – GoldSpark Nov 12 '21 at 21:56
  • 1
    To be clear, `delete node; node = NULL;` is valid, you can reset to NULL (not necessary in this case). The problem related to `delete node; if(node->parent == nullptr){}` – Barmak Shemirani Nov 12 '21 at 22:11
  • Yeah thats what I did in while loop I have set that node to nullptr and it worked like that. – GoldSpark Nov 13 '21 at 16:42