Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In what context does the delete operator throw an error?

In my implementation of a linked-list, my helper function deleteNode(Node*) that deletes inner class Node instances is throwing a runtime error, by "triggering a breakpoint" in the Local Windows Debugger in VS 2015. I am being careful to match my new and delete operators. Does scope/reference play a role that I don't realize?

Even if there is a logic error in clear() and deleteNode() gets passed nullptr, it shouldn't throw an error to delete nullptr, and then assign nullptr to itself right? What is the issue with that delete?

class LinkedList {
public:
    LinkedList() : head(nullptr) {}
    ~LinkedList() { clear(); }

    void push_front() {
        head = createNode(head);
    }

    void clear() {
        Node* current_node = head;
        while (current_node != nullptr) {
            Node* next_node = current_node->next; // buffer
            deleteNode(current_node);
            current_node = next_node;
        }
    }

private:    
    struct Node {
        Node(Node* next)
            : next(next) {}
        Node* next;
    };
    Node* head;
    Node* createNode(Node* next) {
        return new Node(next);
    }
    void deleteNode(Node*& toDelete) {
        delete toDelete; // ***VS 2015 puts breakpoint here***
        toDelete = nullptr;
    }
};

int main() {
    auto A = LinkedList();
    A.push_front();
    A.clear();
    return 0;
}

I have removed all attributes and methods not relevant to the error. This dummy code still throws the same error.

like image 700
Aposhian Avatar asked Feb 23 '16 07:02

Aposhian


2 Answers

The problem lies within your clear() function. You see, you think that because of the way you've written your deleteNode function, all your nodes will be nullptr after clear. That is unfortunately not true. You copy your head into current_node, and the copy of head (i.e. current_node) turns into nullptr when it gets deleted, but head remains non-null. Later the destructor attempts to delete it again. Calling delete on already freed memory results in Undefined Behavior.

To fix, add

 head = nullptr;

in the end of your clear function

like image 147
Armen Tsirunyan Avatar answered Oct 19 '22 20:10

Armen Tsirunyan


In what context does the delete operator throw an error?

A delete expression can throw, if the destructor itself throws, or a destructor of a sub object. But you should avoid throwing in a destructor.

A delete expression might also have undefined behaviour if you try to delete a pointer that does not point to a valid object. An exception is nullptr, which is safe to delete. Typical causes for accidentally deleting an invalid pointer is trying to delete same pointer value twice, or forgetting to initialize memory. Undefined behviour can result in anything, including an error being thrown.

What is the issue with that delete?

You're deleting the same pointer twice. You can verify that by checking the value in a debugger.

like image 37
eerorika Avatar answered Oct 19 '22 19:10

eerorika