Is it needed to delete unused new structs within a function? - c++

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.

Related

How is this singly linked list destructor causing an infinite loop?

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
};

List with nodes destructor

Before asking my question, I'm aware of this and this questions.
I have a chained List where each node points to the next node. Basically :
class List{
class Node{
Node():next_(NULL){}
~Node(){
if(next_){
delete next_;
next_ = NULL;
}
}
Node* next_;
}
List():head_(NULL),tail_(NULL){}
void add_node(){
tail_->next_ = new Node();
tail_ = tail_->next_;
}
Node* head_;
Node* tail_;
}
I removed all the useless information but the piece of code given above is
enough to get the idea (at least I hope, I'll update it on request).
What concerns me is the destruction part. Assume I have a List where I have
added many node with add_node(). When the List destructor is called, it
recursively calls the destructor of each Node until it reaches the last node
which has next_==NULL. The List is therefore destructed from the end.
I have never had any issue with this until today where I had a list with
~180000 elements (quite a large memory usage but definitely not overwhelming
the RAM) which returns a segfault...
If I do a while loop destroying the last elements (no recursive call of the
destructor) everything works fine.
Is there a limiting number of recursive call of a destructor ? Did I miss
anything else ?
this way recursion can be avoided:
~Node(){
while(next_)
{
Node* temp = next_->next_;
next_->next_ = NULL;
delete next_;
next_ = temp;
}
}

Why am I getting an uninitalized heap memory error when using a pointer (C++)?

I am tasked with writing a simpler compiler in C/C++. The main() function calls the function parse_program() below in order to read in all of the input from the console and store it in a linked-list graph.
For some reason, my program breaks here:
while (node != NULL){
if (node->id == ID) //Breaks here
...;
node = node->next;
}
With a memory access violation at 0xCDCDCDCD. Research into this shows that I have uninitialized heap memory. Doing a little experimenting, I realized that immediately after creating the node, node->next at location 0xCDCDCDCD.
struct Node* parse_program(){
struct Node* node = new Node;
cout << node;
cout << node->next;
...;
return node;
}
Outputs
0044A940
CDCDCDCD
The above function is the first thing called in the program. I do have global variables.
Am I allocating memory for the node incorrectly? Could an unitialized array/pointer or something elsewhere in the program cause an error even before said array/pointer is called?
Thanks for any advice. I'm stumped on where to start looking for the problem.
Here are the options I know how to fix it:
You may set node->next = NULL; manually right after the node = new Node;;
You may use new Node() with the parens if Node doesn't have any user-provided constructors (e.g. struct Node { Node *next; };) See more details about value-initialization here: http://en.cppreference.com/w/cpp/language/value_initialization
You may want to add a default constructor to Node to make the initialization of next automatic.
Here is how to add a constructor:
struct Node {
Node() : next(NULL) {}
Node *next;
...
};
new Node will call your default constructor Node(), which will set the next data member to NULL for you.
If you omit the constructor, C++ will use the implicit Node() {} with new Node, which keeps next uninitialized (and its value undefined), so when you print it, you get random junk.

C++ Finding Bugs in Code related to linked lists

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.

C++ linked list memory management

I'm attempting to craft my own basic singly linked list in C++ as a learning exercise, and I'm encountering some difficulty in the memory management department. As it stands I have...
A 'Node' class:
class Node
{
public:
char *value;
Node *next;
Node();
~Node();
};
Node::Node()
{
}
Node::~Node()
{
delete[] value;
}
And then my list (I've omitted certain method calls for brevity):
class LinkedList
{
private:
Node *head;
public:
LinkedList();
~LinkedList();
void Add(char **x);
};
LinkedList::LinkedList()
{
head = 0;
}
LinkedList::~LinkedList()
{
Node *temp;
Node *current = head;
while(current)
{
temp = current;
current = current->next;
delete temp;
}
}
void LinkedList::Add(char **x)
{
Node *nodeToAdd = new Node();
nodeToAdd->value = *x;
nodeToAdd->next = NULL;
Node *current = head;
if(!head)
{
head = nodeToAdd;
return;
}
while(current->next)
{
current = current->next;
}
current->next = nodeToAdd;
}
I'm attempting to use this code as follows (again I've omitted things for brevity):
int main()
{
LinkedList *list = new LinkedList();
char *alpha = "alpha";
char *beta = "beta";
char *charlie = "charlie";
char *delta = "delta";
char *echo = "echo";
list->Add(&alpha);
list->Add(&beta);
list->Add(&charlie);
list->Add(&delta);
list->Add(&echo);
delete list;
}
The last call in main to delete the list produces an error:
Debug Assertion Failed! Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
What am I doing wrong here?
The data pointed to by the various Node::value aren't dynamically allocated, so you shouldn't delete them. Applying the concept of "ownership", nodes should either make their own copies of data, which they own and can delete, or nodes don't own data, so they shouldn't be responsible for deleting it.
You can also implement multiple ownership using reference counting, like Objective-C does (see Objective-C Memory Management Rules for more info) but you have to be careful to avoid ownership cycles. You often find some type of reference counting in third-party smart pointers, such as Boost's smart_ptr library. Since you're doing this for the learning experience, it may make more sense to roll your own than use a library. Of course, you could also use a library for now, letting you focus on whatever you're trying to learn.
One day a student came to Moon and said: “I understand how to make a better garbage collector. We must keep a reference count of the pointers to each cons.”
Moon patiently told the student the following story:
“One day a student came to Moon and said: ‘I understand how to make a better garbage collector...
you are trying to release the memory which is not allocated on heap.
char *alpha = "alpha"; --- not allocated on heap
calling delete[]in Node destructor would lead to heap corruption.
Some points:
1) initialize pointers properly in the constructor:
Node::Node():value(NULL),next(NULL)
{
}
2) Take a ownership of value.
Allocate the memory on heap and copy
the contents
You shouldn't release a pointer use delete[]/delete if it's not created by new operator. There are some actions under the hood for the delete[] operation, like releasing/reclaiming marked memory from a managed pool. Since your pointer doesn't belong to these stuff, there will be a problem. IMHO, the underlying delete[] code is the _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) stuff.
The problem is that you're assuming that you can delete the data inside node, but you're passing in pointers to string literals instead, which you can't delete.
If you're assuming that the Node object controls the lifetime of the data inside it, your Node constructor or the Add function in LinkedList will have to make a copy of the data that it is being passed.
In your destructor, you are trying to array delete (delete [ ]) a static string. You have change your Add function to reserve the string and copy it first. See the code below.
However, if I were you and fairly new to memory management, I'd really use something like CString instead of a raw "char *" as it's much easier to deal with.
void LinkedList::Add(const char *x)
{
Node *nodeToAdd = new Node();
int len=strlen(x);
nodeToAdd->value = new char [len+1]; // room for string + terminating 0
strcpy(nodeToAdd->value,x);
nodeToAdd->next = NULL;
Node *current = head;
if(!head)
{
head = nodeToAdd;
return;
}
while(current->next)
{
current = current->next;
}
current->next = nodeToAdd;
}
value and next in Node class doesn't have memory allocated. You should allocate memory in Node's constructor.