I 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 attempt 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;
}
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.)
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).
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
Related
I have created a function to append a node at the front of a linked list in c++. If I don't comment the last line i.e. the delete temp line, the program runs into an infinite loop but if I comment it, everything runs fine. I was hoping to free the memory allocated to the pointer temp to avoid memory leak. Why is it causing a problem?
void addFront(Node **head, int item)
{
Node *temp = new Node(); // Allocating new memory.
temp->data = item; //Storing data in the node.
temp->next = *head; //Linking temp pointer to head pointer.
*head = temp; //Resetting the head pointer as the new first node.
//delete temp; //Deallocating memory.
}
You are calling 'new' once, so you only allocated node once. There is no need to "avoid leak" since you never copied the node.
Don't confuse pointers with the pointee. delete temp deletes the object pointed to by temp, but that is the node you just inserted in your tree.
You do not need to manually manage the memory of the pointer itself, because it uses automatic storage.
new Node(); does more than allocating memory. It allocates memory and creates a Node by calling its constructor. Instead of two phase construction, members should be initiliazed by calling the constructor.
Slightly modified comments:
void addFront(Node **head, int item)
{
Node *temp = new Node(item,*head); // create new node. temp is a pointer to it
*head = temp; // head points to the new node
//delete temp; // delete the new node ?!?
}
There is no memory leak, because now *head does point to the newly created node.
This is a memory leak:
void foo() {
int* x = new int;
}
because after the function returns you have no way to access x and have no way to release its memory. While this is not a memory leak:
void bar() {
int * x;
}
As mentioned above, x itself uses automatic storage and its memory is released automatically when the function returns. Colloquially we say: x is allocated on the stack.
Why is it causing a problem?
If the purpose of the function is to add a new node, then it should follow that there would be more nodes after the function than there were before calling the function.
If you create one node, and delete it, then there would be no more nodes after the function than there was before. This contradicts with the described postcodition that there should be more nodes than there was before.
You haven't shown the part of the program where you do this, but presumably you somehow use the list after you've created it. You cannot use nodes that you've already deleted.
If I don't comment the last line i.e. the delete temp line, the program runs into an infinite loop
Deleting the node there is the wrong way to fix the infinite loop that you haven't shown.
I was hoping to free the memory allocated to the pointer temp to avoid memory leak.
You will have to follow the following order of operations:
Create node
Use node
Free node
You cannot do the following. It won't work:
Create node
Free node
Use node (can't do this after freeing the memory)
I'm stuck on a linked list destructor for my class. This is what I have here:
LinkedList::~LinkedList()
{
LinkedList *forward = nullptr;
LinkedList *current = this;
//iterate through list, deleting each element as we go
while (current != nullptr)
{
//set next pointer to current's next
forward = current->next;
delete current; //delete the current memory
current = forward; //reset current to next's pointer
}
}
When I run it, I get a seg fault. I only want to delete just one node from my linked list. Is that possible? Also, I wasn't given a "head" pointer as I was used to from other lists, so I used "this" instead, does that work?
Aka - the .cpp is finding the spot in the linked list to delete, reorganizing the next pointers around it, and then deleting the node (which calls this destructor)
(when I run my program with an empty destructor, it prints out fine, but of course there are memory leaks)
Any help is appreciated!
by definition delete calls LinkedList::~LinkedList, so you have several (in fact infinite) calls to it because of the loop calling delete, so you access to already deleted element with an undefined behavior
just do
LinkedList::~LinkedList()
{
if (next != nullptr)
delete next;
}
or just
LinkedList::~LinkedList()
{
delete next; // delete on nullptr does nothing
}
even personally I prefer to compare to nullptr first
I argee with bruno.
Besides, when you want to delete a node and you don't have the pointer to head, you need a double-linked list.
The double-linked list has two pointers to its prev and next node.
when you need to delete a node, like this:
ListNode* p;
if(p->pre)
p->pre->nxt = p->nxt;
if(p->nxt)
p->nxt->pre = p->pre;
p->nxt = p->pre = NULL;
delete p;
I implement the following code to delete element at Head. When program runes to "delete p", it will impact the previous Head and Head gets to NULL. What happened?
Node<T>* p;
p = Head;
Head = Head->next;
delete p;
This function will delete the 1st node (node
pointed to by head). It returns true if the node was deleted else false if the list is empty.
Using double pointers for the input parameter (head) here because head will
have to be updated and this value should reflect
outside this function.
bool deleteHeadElement(Node** head)
{
if (*head == nullptr)
{
// List is empty, nothing to delete
return false;
}
// Store the node that has to be deleted
Node* nodeToDelete = *head;
// Update the head to point to next nodeToDelete
*head = nodeToDelete->next;
delete nodeToDelete;
// 1st element of node has been deleted.
return true;
}
After the call to this function, you may subsequently call it and it will take care of the scenario in which the list becomes empty after the previous calls.
NOTE:
Regarding the value 0xfeeefeee, it seems you are trying to somehow freeing already freed memory. Perhaps you should check if your head is properly getting updated.
Also, make sure that you are freeing memory of the node by using delete only if it was allocated using new. delete takes care if the memory to pointed is NULL.
If you had allocated memory to the node using malloc(), you should be deallocating using free().
I have a class called "node". I link a bunch of node objects together to form a linked list. When the "node" destructor is called, it only deletes the first node. How do I iterate through the entire linked list of nodes and delete each node object?
Here is the class definition:
class Node
{
private:
double coeff;
int exponent;
Node *next;
public:
Node(double c, int e, Node *nodeobjectPtr)
{
coeff = c;
exponent = e;
next = nodeobjectPtr;
}
~Node()
{
printf("Node Destroyed");
}
The destructor is called by invoking delete on the pointer to the first node of the linked node list.
Since you don't know how many nodes there are in a list, if you do not have firm bounds on that it's not a good idea to invoke destructors recursively, because each call uses some stack space, and when available stack space is exhausted you get Undefined Behavior, like a crash.
So if you absolutely want to do deallocate following nodes in a node's destructor, then it has to first unlink each node before destroying it.
It can go like this:
Node* unlink( Node*& p )
{
Node* result = p;
p = p->next;
result->next = nullptr;
return result;
}
Node::~Node()
{
while( next != nullptr )
{
delete unlink( next );
}
}
But better, make a List object that has ownership of the nodes in a linked list.
Of course, unless this is for learning purposes or there is a really good reason to roll your own linked list, just use a std::vector (and yes I mean that, not std::list).
How do I iterate through the entire linked list of nodes and delete each node object?
It would be cleaner if you had a separate class to manage the entire list, so that nodes can be simple data structures. Then you just need a simple loop in the list's destructor:
while (head) {
Node * victim = head;
head = victim->next; // Careful: read this before deleting
delete victim;
}
If you really want to delegate list management to the nodes themselves, you'll need to be a bit more careful:
while (next) {
Node * victim = next;
next = victim->next;
victim->next = nullptr; // Careful: avoid recursion
delete victim;
}
Under this scheme, you'll also need to be careful when deleting a node after removing it from the list - again, make sure you reset its pointer so it doesn't delete the rest of the list. That's another reason to favour a separate "list" class.
I have a pointer to a node, I want to delete that particular node from linked list.
The below logic works fine, But it fails if node to be deleted is Last node.
How to delete the last node?
void deleteNodWhosePointerIsGivene(node *pointerNode)
{
node *temp=pointerNode->next;
pointerNode->id=temp->id;
pointerNode->next=temp->next;
free(temp);
}
First of all you are not removing pointerNode from the list, you are removing the next node in the list. Secondly you are not checking if there is a next node or not.
Think about what you are trying to do.
You are trying to delete the next object in the list.
You are at the end of the list, therefore the temp pointer will be null.
You are then trying to get the next from null and also trying to free null.
Normally I would do something along the lines of.
DeleteObject(*obj)
Get Next Object
Get Prev Object
Set Prev->next = Next
Set Next->prev = Prev
Delete obj;
If I am understanding you comments above you are wanting to do a copy then your code should look like.
DeleteObject
Get Next Object
if (Next Object is not null)
This.Id == Next.Id
Free Next
else
Throw exception "Cannot delete last object in list"
There is no way to set the pointer in the second to last object in the list if you want to delete the last object in the list. The only way to do this is to either use a double-linked list, or iterate down the list looking for the pointer you wish to delete and keep track of the last object in the list.
You aren't deleting pointerNode in your code, You are deleting pointerNode->next.
Looking at your example of a single linked list. Let's say we have:
1->2->3->4->5
You pass in a pointerNode of "3". Your code then does the following:
1) Assigns pointerNode->Next to temp i.e. "4"
2) pointerNode->Next will be assigned temp->Next i.e. "5"
3) temp is freed i.e. "4"
so your list after this would be 1->2->3->5.
When you get to node "5" then you will get an access violation
1) pointerNode->next is assigned to temp i.e. NULL
2) pointerNode->Next will be assigned temp->Next i.e. access violation as you reference a NULL pointer.
A doubly linked list would be a better solution as to delete pointerNode you need to change the Next pointer of the previous node. Otherwise you'd have to scan the list first to find the node prior to pointerNode.
Here's the code which should work for a singularly linked list. Bear in mind this will be quite slow for large lists and I would second Andrew Norman's suggestion of using a doubly linked list.
Anyway.. here goes. In order for this to work you need to pass the root node of the list and beware that the address of this node may get changed if you try to delete it, hence I pass it as a pointer to a pointer.
void DeleteNode (Node **rootNode,Node *pointerNode)
{
Node *prevNode;
if (pointerNode == *rootNode) {
// Head node is being removed
*rootNode = pointerNode->Next;
} else {
// Find the previous node
for (prevNode = *rootNode; prevNode->Next != pointerNode;
prevNode = prevNode->Next) ;
prevNode->Next = pointerNode->Next;
}
// Free the node
free (pointerNode);
}
If you really need to delete the item associated with the node whose pointer you've got, then you have two options when it comes to the last node:
Iterate from the beginning of the list to find its predecessor (the next-to-last node), delete the last node and set it's predecessor's next to NULL.
Take the lazy approach - do not actually delete the node and only mark it as dead (e.g by setting its data to an impossible value.) Delete it later when you reach it from the predecessor (then also NULL-ing predecessor's next).
Both approaches have obvious drawbacks. This is why it is best to always have the predecessor when deleting a node from a linked list.
If you are able to have a reference to the previous node.
void deleteNodWhosePointerIsGivene(structNode* pCurrentNode, structNode* pPreviousNode)
{
// Not the Last Node ?
if(pCurrentNode->pNext)
pPreviousNode->pNext = pCurrentNode->pNext);
else
pPreviousNode->pNext = NULL;
delete pCurrentNode;
pCurrentNode = NULL;
}
Otherwise you will need to have a reference to the First Node of the List, and search for the previous.