There's 2 pieces of code that I can't seem to find the bug with. I know there is something wrong within these. One for each.
int pop()
{
Node* temp = new Node();
temp = tail;
tail->prev()->setNext(NULL);
int tempV = temp->key();
delete temp;
return tempV;
}
The other piece of code is this:
int main()
{
Node* t = new Node(0,NULL);
t = Node(1,t);
t = Node(2,t);
delete t;
}
I thought about the 2 pieces of code for a while. For the 1st piece of code, I think the error is that you shouldn't create the Node* temp on the heap with the keyword new. It should just be Node* temp = tail; I believe. Can anyone confirm that?
For the 2nd piece of code, I thought the error was that you don't need both
t = Node(1,t);
t = Node(2,t);
EDIT::I'm sorry I made a mistake. It was supposed to be Node rather than node. My friend told me it has to do something with memory. It there a memory leak because of the multiple nodes being declared with new? Or do we need the new keyword for the last 2?
Thanks
When you pop the element, you need not create a "new" node. You have to remove the last element of the linked list - not create a new node.
For your second question, you do not need the
t = node(1,t)
t = node(2,t)
if the function returns the currently added node.
But if the function returns the header of the linked list, it is required. It depends on how you write the node function.
you are losing the value you new
Node* temp = new Node();
temp = tail; <-- you just lost the value you new'ed
then later you are deleting a different node
tail->prev()->setNext(NULL); <-- this line doesn't check that the value for prev() isn't null
as to what is going on in main I would need to see more of the code for "node"
Dinesh is correct in the first example. Here is a little more explanation.
Node* temp = new Node()
temp = tail;
results in a memory leak. the new node that was created is leaked when you overwrite temp to tail. The proper way to do it would be
Node * temp = tail;
In the second example its not clear what the node function does. If you meant to write this:
int main()
{
Node* t = new Node(0,NULL);
t = new Node(1,t);
t = new Node(2,t);
delete t;
}
The code would make more sense, it creates a linked list of three nodes containing 2, 1, 0 when listed from head to tail. It's hard to tell from the incomplete example.
In pop you have a memory leak. You construct a Node on the heap and then immediately lose track of it, like inflating a balloon and letting it go:
Node* temp = new Node();
temp = tail;
But you also have a more serious problem: you do not adjust tail. When the function is finished, tail points to a region of memory where the last node used to be, and any attempt to dereference it will cause Undefined Behavior.
As for your second question, the code might be correct, and it might not. There's no way to tell unless/until you show us what node(...) does.
Related
I've started to learn linked lists today, and I am trying to delete nodes.
void deleteEnd(Node* refNode) {
Node* lastNode;
lastNode = new Node;
while((refNode->next)->next != NULL) {
refNode = refNode->next;
}
lastNode = refNode->next;
refNode->next = NULL;
delete lastNode;
}
void deleteIndex(Node* refNode, int index) {
Node *prev, *next, *deleted;
prev = new Node;
next = new Node;
deleted = new Node;
for(int i=1; i < index; i++) {
refNode = refNode->next;
}
prev = refNode;
deleted = prev->next;
next = deleted->next;
prev->next = next;
free(deleted);
}
I can use delete in the first one, but when I try to use it in the second, it doesn't work. The terminal doesn't give any error messages.
I found some information on the Internet, but I couldn't really understand it.
This is my linked list:
class Node {
public:
int data;
Node *next;
};
As pointed out by the comments, there are several things wrong with this code. All issues are from the comments, none are found by me, all credit goes to François Andrieux, Jesper Juhl, Sven Nilsonn, Avi Berger, and Thomas Matthews.
First, the code probably doesn't work because you mixed new and free. new is a C++ API function, while free is from C. Whenever you construct an object with new, which should not be that often with C++'s automatic memory management, you must free it with delete.
Second, when looping through a list, always start at 0. The only reason otherwise would be to start at the second item.
Third, in this passage:
prev = new Node;
...
prev = refNode;
...
prev->next = next;
When you set prev, it is overwriting the previous value. If this is a pointer, as it is, then this causes a memory leak. Always delete it before overwriting.
Finally, in deleteEnd, as pointed out by Thomas Matthews, you are trying to dereference, or get the value from, the pointers, without checking if it is nullptr. If one is, it will cause undefined behavior, and can crash the program.
I wrote a singly linked list implementation using a struct. It is not part of an outer class that manages the operations on the list. Instead all of the operations are handled directly with the Nodes.
I understand that if the struct definition was part of a class, say ListManager, calling the destructor on a ListManager instance would just require one to iterate through the linked list managed by the class and delete each Node.
However, since this linked list is not part of an outer class and manages all of the operations itself I am a bit confused as to how to write the destructor.
Version 1 works well, its a recursive call that goes through the list and frees and memory associated with each Node.
Version 2 caused an infinite loop. I don't understand why, as this is one way that I would implement the destructor for a container class that manages the Node linked list.
Version 3 works well but is too verbose.
I ran all three versions using valgrind and python tutor to check for leaks and other issues.
Any help explaining why Version 2 does not work and why it is incorrect to implement the destructor in such a way is appreciated!
Struct Linked List
#include <iostream>
#include <string>
using namespace std;
struct Node
{
int id;
Node* next;
Node(int newId = 0, Node* newNext = NULL)
: id(newId), next(newNext) { }
};
Destructor Version 1
~Node()
{
if (next != NULL)
delete next;
}
Destructor Version 2
~Node()
{
Node* lead = this;
Node* follow = this;
while (follow != NULL)
{
lead = lead->next;
delete follow;
follow = lead;
}
}
Destructor Version 3
~Node()
{
Node* lead = this;
Node* follow = this;
if (follow != NULL)
{
lead = lead->next;
delete follow;
follow = lead;
}
}
Main
int main()
{
Node* head = NULL;
head = new Node(23, head);
head = new Node(54, head);
head = new Node(81, head);
head = new Node(92, head);
delete head;
return 0;
}
In version 2, you have written a loop that clears up the entire list in one destructor call by looping through the list and deleting every element. However, what happens is not that you have just one destructor call. Every time an element is deleted, that calls the destructor again.
So in the end, the delete follow translates to delete this (because follow = this;) for the first invocation. This then causes the destructor of the first node to be called again, causing the endless loop.
The following nodes would be destroyed multiple times, leading to undefined behavior, but it's not even getting there because of that infinite loop.
You only need each Node to delete (at most) one other Node, to eventually delete all the nodes. You re-assigning of local pointers does not affect the structure of the list.
Both 2 and 3 are delete this, which is suspicious at the best of times, plus some irrelevant ceremony, in the destructor. They are both undefined behaviour, deleting the same object (at least) twice.
Your first attempt is close.
Instead of confusing yourself with copying around pointer values, just use an owning pointer type, like std::unique_ptr.
struct Node
{
int id;
std::unique_ptr<Node> next;
Node(int id = 0, std::unique_ptr<Node> next = {})
: id(id), next(std::move(next)) { }
// correct destructor is implicit
};
I'm trying to improve my C++, so I decided to start fresh and went through a few tutorials.
It seems to be a general rule that each "new" operation has to be followed by "delete" eventually, to avoid risking a memory leak.
Then, I stumbled across the following code segment on a tutorial regarding linked lists:
struct node {
int data;
node* next;
};
class linkedlist {
private:
node* head;
node* tail;
public:
linkedlist(){
head = null;
tail = null;
}
void delete_first()
{
node *temp=new node;
temp=head;
head=head->next;
delete temp;
}
// additional functions for add/delete/display, ...
}
The problem I'm having here, is understanding the delete_first() function completely.
Create a new node in dynamic memory and assign it to 'temp'
Set temp's pointer to now point at the head instead (but what happened to the new node?)
Make the head's subsequent element the new head
Delete temp from memory
I assume that the tutorial would not introduce memory leaks, but it certainly seems to me as if each call of delete_first() would generate an extra struct that's never deleted.
Okay, there's both a 'new' and a 'delete', but wouldn't that suggest that the amount of elements in memory stays the same?
Could anybody please clear me up and elaborate why there's no(?) memory leak happening in this case?
You are correct.
That’s a bug in the tutorial you were reading. It shouldn’t be creating a new node in delete_first(). Instead, it should be setting temp to head when it’s declared.
I am trying to implement a Linked ArrayList in C++ for instruction purposes, I've hit a snag though and I'm unsure how to unsnag it. My pointer array doesn't seem to be composed of pointers, but of actual objects.
Keeping my code as brief as possible.
//arraylist.h//
class classArrayList {
private:
class Node {
Node();
//accessors
};
Node* classArray;
public:
classArrayList();
};
//arraylist.cpp//
classArrayList::classArrayList() {
Node* node = new Node();
this->setHead(node);
this->setMaxSize(5);
classArray = new Node[5];
this->classArray[0] = *node;
this->setSize(1);
}
void classArrayList::deleteNode( int index ) {
Node* my_current = &this->classArray[index];
//blahblah
}
But when I go to delete a node, "my_current" doesn't link to whatever would be next or prev in this list. Trying to delete at position zero, no next.
So there's definately a node with data but it doesn't have its links, but checking the debugger my linked list is fine and works, so its whatever the array is pointing to that's screwing up.
So instead of pointing to the list, its pointing to unique instances, how can I fix this?
My code to add something new to the array is: this->classArray[some_index] = *new_node;
To clarify, I wanna be able to have an array that points sequencially to each object in my linked list. And then when I ask for one at any n in my arraylist, reference it to a pointer and then do thins to the object in my list through its position in the array, rather than increment through the list until I find the nth one I want.
Make your classArray a double pointer and create a Node pointer array. Node* classArray; Copy the address of head of your list to each array.
classArray = new Node*[5];
In your code by your statement this->classArray[0] = *node; you are not storing the address of the newly created, instead content of newly created node. And by deleting you are not removing the dynamically created list head.
For copying the address of newly created list you should use
this->classArray[0] = node;
The code works as it should. When you delete a node from your linked list, you delete the data under the pointer. As you set my_current to the address of the deleted node, you actually don't point to anything. The problem doesn't lie in the code, but in your understanding of the subject.
In order to really make a working linked list, every node should consist of a pointer to the next node. That way, when you delete a node, you'll first be able to retrieve the next node from the pointer, and set your my_current to a valid address.
In order to solve your problem, you should actually read a bit about the subject.
If you want to access the elements in "array style", overload the operator [].
Node& classArrayList::operator [](unsigned int index)
{
Node *node = head;
for(unsigned int i=0;i<index;i++)
if(node->next()) node = node->next();
else break;
return *node;
}
I have a basic linked list problem that I have attempted to solve below. I would appreciate any inputs on my approach, correctness of the algorithm (and even coding style). The problem calls for a function that deletes all occurrences of an int in a circular linked list and returns any node from the list or NULL (when the list is null).
Here's some C++ code that I have so far:
struct Node{
Node* next;
int data;
};
Node* deleteNode(Node* &node, int num){
if(!node){
return NULL;
}
Node* given = node;
Node* del;
while(node->next != given){
if(node->next->data == num){
del = node->next;
node->next = node->next->next;
delete del;
}
node = node->next;
}
//Check if the first node needs to be deleted, with variable node pointing to last element
if(given->data == num){
node->next = given->next;
delete given;
}
return node;
}
The delete node; should be delete del;.
Also, use Node* node as parameter, instead of Node* &node which will prevent non-lvalues from passing in.
p.s. Forgot a semicolon after struct definition? :)
Without following all your logic I can see at a glance this code cannot work.
You are checking for the input list being empty and that's the only case in which your code returns NULL. But what happens if you are passed a list in which all elements must be deleted?
This problem also has a subtlety in it. To check if you completed a circular list you need to compare to the first address to see if you got linked back to the start. However if this element has been deleted then by C++ standard you're not even allowed to use its address in a comparison.
To avoid making two passes over the elements to be deleted one possible trick is to "break the loop" when starting iteration so you can check for NULL instead of checking for the address of the starting node.