views:

109

answers:

3

New to c++, and am having a problem with delete and destructor (I am sure i am making a stupid mistake here, but haven't been able to figure it out as of yet).

When i step through into the destructor, and attepmt to call delete on a pointer, the message shows up "Cannot access memory at address some address."

The relevant code is:

/*
 * Removes the front item of the linked list and returns the value stored
 * in that node.
 *
 * TODO - Throws an exception if the list is empty
 */
std::string LinkedList::RemoveFront()
{
    LinkedListNode *n = pHead->GetNext(); // the node we are removing
    std::string rtnData = n->GetData(); // the data to return

    // un-hook the node from the linked list
    pHead->SetNext(n->GetNext());
    n->GetNext()->SetPrev(pHead);

    // delete the node
    delete n;
    n=0;

    size--;
    return rtnData;
}

and

/*
 * Destructor for a linked node.
 *
 * Deletes all the dynamically allocated memory, and sets those pointers to 0.
 */
LinkedListNode::~LinkedListNode()
{
    delete pNext; // This is where the error pops up
    delete pPrev;
    pNext=0;
    pPrev=0;
}
+5  A: 

It seems that you are deleting the next and previous nodes of the list from the destructor. Which, if pNext and pPrev are LinkedListNode*, means that you are recursively deleting the whole list :-(

Try this:

std::string LinkedList::RemoveFront()
{
    LinkedListNode *n = pHead->GetNext(); // the node we are removing
    std::string rtnData = n->GetData(); // the data to return

    // un-hook the node from the linked list
    pHead->SetNext(n->GetNext());
    n->GetNext()->SetPrev(pHead);

    n->SetNext(0);
    n->SetPrev(0);
    // delete the node
    delete n;
    n=0;

    size--;
    return rtnData;
}

LinkedListNode::~LinkedListNode()
{
}

(Actually you don't even need to reset the prev and next pointers to 0 since you are going to delete the node anyway. I left those statements in because they at least put the node into a consistent state, which is a good idea in general. It may make a difference if you later e.g. change your memory management strategy and decide to store unused nodes for later reuse.)

Péter Török
The next and previous nodes stored in the current node (each node contains some string data, and a pointer to the next and previous nodes in the list). That is the desired behavior, as we have un-hooked this node from the linked list, and now want to return all the dynamically allocated memory EDIT - wait, i think see what you are saying..
kyeana
@kyeana: you only want to return the memory associated to the single Node that you're removing
Mike Dinsdale
It's worse than that -- this actually will delete forwards until the end of the list (recursing on the first delete) and then try to delete the second-to-last node again from inside the last node's destructor, which is likely where the crash is. If X, Y and Z are the last three nodes, ~X is deleting Y, ~Y is deleting Z, and ~Z is deleting Y again.
Adam Rosenfield
Ok, that makes sense. I knew i was doing something stupid :)Thanks for the help.
kyeana
@Adam Good point.
Péter Török
It's even worse. Z tries to delete whatever its "Next" points to, which is probably either NULL or a random location in memory.
Beta
@Beta AFAIR deleting a null pointer is OK, it does not have any effect. Deleting a dangling pointer is of course very not OK. But I would assume the linked list is terminated correctly with a null pointer - the OP wouldn't have got even this far if he had forgotten about that :-)
Péter Török
I love the sad face after you mention he is recursively deleting the whole list
Carson Myers
+1  A: 

It seems that your LinkedListNode is deleting its neighbours, so when you delete one node it then proceeds to destroy the entire list - note you don't set pNext and pPrev to NULL when you remove your node.

Also your LinkedListNode destructor is problematic even in the case when you want the whole list to be destroyed: having both delete pNext and delete pPrev will lead to multiple calls of the same destructor (and I think eventually a stack overflow).

Mike Dinsdale
oh god... node 2 deletes nodes 1 and 3, which both try to delete node 2, which deletes nodes 1 and 3 twice each, and then node 2 is deleted again four times, ...
Carson Myers
A: 

Actually you shouldn't be messing with neighbours in a node. That's for list class to do - connect them properly. In the destructor you can set them to null, but unless you have allocated dynamically something else - you don't have to call delete

raceCh-