Delete a Linked List before closing a C++ program? - c++

I have a doubt which is as follows...
Linked List deals with pointers and dynamic allocation. So they have provided a keyword new which allocates a chunk(that's how it's spelled I suppose) of memory in the heap store and returns a pointer pointing to it. And they have also provided the delete keyword which frees the memory to which the pointer returned by the new is pointing.
So suppose I've created a Linked List of say 10 nodes then should I have to create a function to scan through each node and delete each node? Because in my textbook they have written that if you don't delete a dynamically allocated object then it causes memory leak...
So in short do I have to scan through each node deleting each node before closing a C++ console application??
Aditional Details
Operating System Windows 7
Compiler Turbo C++

It is a good practice that for each memory allocated, there is a class or function responsible for freeing it if it won't be used any more.
Still, all the memory used by program will be freed by operating system when the program is closed. But I think that your teacher (homework, isn't it?) or boss would rather you freed the memory.
The bottom line is: delete everything you created with new.

So in short do I have to scan through each node deleting each node
before closing a C++ console application??
Sure you can delete it before closing your problem, if you did not delete it, then operating system will anyway clear memory consumed by your application / program.
Once, if you know, your heap memory is no more useful better to delete it (instead of waiting for closing program)
{
Allocation with new...
call function(using allocated memory)
....
....
call function2(using allocated memory)
not using allocated memory here after..
**Delete Your heap memory..**
call AnotherFunction()
....
...
Alternatively, you can release / delete memory here also. (Good practice than not deleting :) )
end of main / application.
}

No, you don't actually have to do so.
Nearly all code should, however, be written in a way that the data gets deleted when the object that owns it goes out of scope, so this will happen (almost) unavoidably.
In other words, you should not normally have something like:
// WARNING: bad code. Avoid this, or anything similar.
struct node {
int data;
struct node *next;
};
node *head = NULL;
int main() {
node *t = new node;
t->data = 1;
t->next = head;
head = t;
t = new node;
t->data = 2;
t->next = head;
head = t;
// here, do we bother to delete the two nodes or not?
};
Instead, what you normally want to do is create a class that encapsulates all the work, and in its destructor it frees all the memory it owns:
class linked_list {
struct node {
int data;
node *next;
node(int data, node *next = NULL) : data(data), next(next) {}
} *root;
public:
void add(int data) {
root = new node(data, root);
}
~linked_list() {
node *prev = root;
for (node *temp = prev->next; temp!=NULL; temp=temp->next) {
delete prev;
prev = temp;
}
delete prev;
}
};
With a class like this, there's really no decision to make:
int main() {
linked_list x;
x.add(1);
x.add(2);
}
When execution reaches the end of the block in which x was defined, x goes out of scope and gets destroyed. In the process, its destructor is invoked, and that deletes the nodes in the linked list (modulo any bugs in my code, of course). There's no need to think or care about whether it makes sense to delete the nodes in this case, because it simply happens automatically every time.
Note that I'm not saying this code is (even close to) 100% ideal either. With a compiler modern enough to support it you'd almost certainly want it to be a template to allow storing an arbitrary type, and use a unique_ptr and make_unique instead of a raw pointer and raw new. Unfortunately, I have little choice but to leave these out, since I'm sure Turbo C++ doesn't support unique_ptr, and doubt it supports templates either. For real use, this should also include a copy constructor and assignment operator as well, so assigning and copying linked lists would work correctly (as it stands now, either will typically lead to problems because it'll end up attempting to destroy the nodes in the linked list twice).
Final note: of course, you usually shouldn't write your own linked list code anyway. But when/if you do have a reason to writer a container (or something similar) it should clean up its own mess, so to speak. One of the real strengths of C++ is deterministic destruction; use it.

Related

Can't deallocate memory at the end of the function

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)

Adding node to linked list without explicitly allocating memory space (without using new)

So I was learning how to make a linked list, and I was wondering why we need to use "new" when adding a node. Below is function that adds a node correctly:
void addNode(int value){
Node* new_node_ptr = new Node;
new_node_ptr->value = value;
if (root == NULL){
root = new_node_ptr;
traveler = new_node_ptr;
} else {
traveler->next = new_node_ptr;
traveler = new_node_ptr;
}
}
But, since I am new to c++, when I tried to figure out how to do this by myself, instead of having the line:
Node* new_node_ptr = new Node;
I wrote:
Node new_node;
Node* new_node_ptr = &new_node;
This doesn't work. It seems that the new_node variable keeps being assigned to the same memory address each time you try to add a new node. This is simultaneously fascinating and infuriating. Could anybody explain this c++ weirdness to me?
Thanks!
When you write
Node new_node;
The variable is created on the stack and should not be used once addNode exits. addNode loses "ownership" of that memory once the function exits, and memory associated with new_node is allowed to be used again by other parts of your program. Attempting to use it is undefined behavior and cannot be relied upon.
You must allocate memory dynamically to ensure that the life of the data extends beyond the scope of the function.
In the second case with stack allocation, if new_node is always assigned memory at the same address, that's just how it happens to work out in your test case. Depending on the order of other functions being called before addNode, that may not always happen, and likely won't consistently in a "real program".
When you declare a variable without using new, you are saving a portion of memory allocated in the stack. Variables stored in the stack belong inside a function but not outside (for example, a counter, iterators, etc.).
When you declare by using new, you save a portion of memory allocated in the heap. Variables stored in the heap can be accessed in your entire program (and, by some methods, by other programs too).
You can find more detailed information in the following link:
https://www.gribblelab.org/CBootCamp/7_Memory_Stack_vs_Heap.html
Node* new_node_ptr = new Node;
The above means "create a new node object and keep it indefinitely long".
Node new_node;
Node* new_node_ptr = &new_node;
The above does not mean "create a new node object and keep it indefinitely long".
If both versions did what you want them to do, now that would be weird, because then ithe new construct would appear to serve no legitimate purpose whatsoever.

C++: Assigning pointers in a class to NULL before calling "delete"

Is it necessary to assign all pointers in a class to NULL before deleting? I mean, from example, for the following snippets of a function that deletes a node in a binary search tree,
1.
Node *temp = parent->left;
parent->left = temp->left;
delete temp;
2.
Node *temp = parent->left;
parent->left = temp->left;
temp->left = NULL;
delete temp;
Is the line
temp->left = NULL;
necessary? Some tutorials do it while others don't.
Depends. If the destructor of Node deletes the child nodes, then it is necessary. If it doesn't then that line is not necessary. Yet some tutorials might include it solely in order to promote a good programming style. If you introduce a bug to your program and use the pointer after deleting it, then having a null pointer will give you an error message instead of undefined behavior. You might also want to add the line temp = NULL; if you want to follow this style more rigorously.
It probably isn't necessary. No code can safely dereference temp after it has been deleted. As noted by Ralph Tandetzky however, it is valid if Node has a destructor which operates on its left member
One other possible benefit of NULLing its members is to catch invalid access more predictably.
No the line
temp->left = NULL;
is not necessary. In many cases it can be helpful if you force yourself to add this line after every delete because you will be able to easily identify the error if your program crashes and you see the pointer set to zero.
It is not strictly necessary, this is a measure designed to help in debugging. Imagine that you left that pointer without a NULL (e.g., in a linked list), and somehow you stepped into memory that has been freed, but its contents have not been deleted. Then there exists the danger that you can follow that pointer, without actually knowing whether it still exists or not, and maybe trying to delete that memory when it has already been deleted.
So, it is just safety, not something designed to achieve any functionality.
There is another (complementary) way to achieve the same: detect whether the memory being accessed has been deleted or not. For example:
class Node {
public:
Node()
{ status = 0xf00dbeef; }
~Node()
{ status = 0xdeadbeef; }
// ...
private:
int status;
bool isAlive() const
{ return ( status == 0xfoodbeef ); }
};
This way, you can always assure that you are using memory that was correctly allocated, i.e. it was a) not freed and b) it actually stores a Node object.
Hope this helps.
No, this is not needed, but if the memory pointed to by left pointer is owned by the object, you should delete it in turn.

Query related to memory management in C++

Hi i have a general query regarding memory management in C++.
With the help of this program only i understood that new is used to allocate memory on heap and temporary variables are allocated memory on stack.And that if we are allocating memory on the heap we have to free it also manually else there will be memory leak.
But in the program i am updating an object of BST struct in a function named Insert by creating a new variable temp of type BST on heap.But then i am not sure how to free that memory.If i use the free command at the end of the function i.e free(temp) then the value stored at that memory will be lost and i will get an error if i try to access it again,and i certainly cannot use free(temp) in main as it is not a local variable to main.
Can some one tell me what should be done.
Btw i must mention that without using free(temp) also my program is working correctly but then i guess memory leak is happening which is bad.
Also i am a little confused as why my program is running without errors if i comment the destructor ~BST() but giving linker errors when i uncomment it.
#include<iostream>
#include<string>
#include<conio.h>
#include<array>
#include<stack>
#include<sstream>
#include<algorithm>
#include<vector>
#include<ctype.h>//isdigit
#include<deque>
#include<queue>
#include<map>
using namespace::std;
struct BST
{
int data;
BST *left;
BST *right;
BST(int d,struct BST* l,BST *r):data(d) , left(l) ,right(r)
{
}
BST()
{
}
//~BST();
};
void levelOrder(struct BST *root)
{
struct BST *temp=NULL;
int count =0;
deque<struct BST*> dq;
if(!root)
{
return;
}
dq.push_back(root);
count=dq.size();
while(!dq.empty())
{
temp=dq.front();
cout<<temp->data<<" ";
if(temp->left)
{
dq.push_back(temp->left);
}
if(temp->right)
{
dq.push_back(temp->right);
}
dq.pop_front();
if(--count==0)
{
cout<<endl;
count=dq.size();
}
}
}
void Insert(struct BST*root,int data)
{
//struct BST temp(data,NULL,NULL);
BST *temp = new BST(data,NULL,NULL);
temp->data =data;
temp->left= NULL;
temp->right=NULL;
if(!root)
{
return;
}
while(root)
{
if((root)->data >data)
{
(root)=(root)->left;
if(!(root)->left)
{
(root)->left=temp;
break;
}
}
else
{
(root)=(root)->right;
if(!(root)->right)
{
(root)->right=temp;
break;
}
}
}
}
int main()
{
deque<struct BST> dq1,dq2;
BST e(4,NULL,NULL);
BST f(3,NULL,NULL);
BST d(1,&f,NULL);
BST b(2,&d,&e);
BST c(8,NULL,NULL);
BST a(6,&b,&c);
levelOrder(&a);
Insert(&a,5);
cout<<a.left->right->right->data;
cout<<endl;
levelOrder(&a);
_getch();
return 0;
}
First, in C++ you should generally use new and delete (they call ctors/dtors, etc.) For arrays, use delete[]. new/delete is not compatible with malloc/free.
I guess BST is a binary search tree. So you have a tree of dynamically allocated memory.
You must free this whole tree, and which means you should do it in order too, lest you get dangling pointers.
One could significantly reduce the complexity by making sure that a BST-node always free's its children. Then when you delete the root node, it will recursively delete all the other nodes.
In my opinion, the easiest way to do this is to use a smart pointer, like shared_ptr<T>, unique_ptr<T> or auto_ptr (the last one has caveats, but I'm not gonna address them here.)
The structure would then look like:
struct BST
{
/* ctor, dtor omitted for brevity. */
std::unique_ptr<BST> left;
std::unique_ptr<BST> right;
}
Your BST-node goes out of scope, that is, you delete it, or it is allocated on the stack and the code exits the block. The destructors for left and right is called and the unique_ptr implementation makes sure to call delete on the pointer it stores.
The BST *temp created in your Insert method is the new node/subtree that you insert, you don't want to delete it until either the entire tree is destroyed or the node is deleted in some kind of Delete function that you haven't written yet.
Regarding your last point:
Running this particular program without a destructor will leak memory, but not access any invalid memory segments, that's why it runs without any errors.
When you uncomment the destructor declaration in your code, you get linker errors because you haven't defined the destructor, you have just told the compiler/linker that there should be a destructor, but there is none. Even if you just want an empty one, it would have to be ~BST() {}.
Both constructors should assign default values to the left right members, at least NULL;
They should not be assigned values outside the class. Add default parameters to the constructor. To avoid leakage you should not create the object until you need it. Alternatively have a flag, initially false, that you set to true if you've used it. And then delete on return if the flag is still false.
First of all, you should use new and delete for memory management in C++, not malloc() and free().
With that said, note that you assign another pointer, either left or right to point to the memory which is originally allocated to the variable temp. Your tree will give you access to the allocated memory, albeit via other variables than the original temp variable. This means that you can delete the memory using these variables in your BST class. Typically this is done inside the destructor.
Note that you are managing memory here, not variables. Let's look at the difference with a simple example:
int main() {
int* intPtr = new int;
int* temp = intPtr;
delete temp;
temp = NULL;
}
As you can see, this code allocates a single block of memory to store an int. This memory has two pointers to it. You can delete the memory with either pointer, just as long as you don't delete with both. This is definitely a balancing act when you learn about memory management. You must be sure that all memory is deallocated while never attempting to deallocate the same block of memory twice.

What's the best way to resolve this scope problem?

I'm writing a program in python that uses genetic techniques to optimize expressions.
Constructing and evaluating the expression tree is the time consumer as it can happen
billions of times per run. So I thought I'd learn enough c++ to write it and then incorporate it
in python using cython or ctypes.
I've done some searching on stackoverflow and learned a lot.
This code compiles, but leaves the pointers dangling.
I tried this_node = new Node(... . It didn't seem to work. And I'm not at all sure how I'd
delete all the references as there would be hundreds.
I'd like to use variables that stay in scope, but maybe that's not the c++ way.
What is the c++ way?
class Node
{
public:
char *cargo;
int depth;
Node *left;
Node *right;
}
Node make_tree(int depth)
{
depth--;
if(depth <= 0)
{
Node tthis_node("value",depth,NULL,NULL);
return tthis_node;
}
else
{
Node this_node("operator" depth, &make_tree(depth), &make_tree(depth));
return this_node;
}
};
The Node object returned by make_tree() is just a temporary object, it will automatically be destroyed again at the end of the expression in which the function is called. When you create a pointer to such a temporary object, like in &make_tree(depth), this pointer will not point to anything useful anymore once the temporary object got destroyed.
You should use real dynamic memory allocation with new and delete to build the tree, so that you don't end up with pointers to not longer existing objects. Probably this construction of the tree should be done in a constructor of the Node class, the destructor should then take care of the deletes needed to release the used memory. For example:
class Node {
public:
const char *cargo;
int depth;
Node *left;
Node *right;
Node(int a_depth);
~Node();
};
// constructor
Node::Node(int a_depth) {
depth = a_depth;
a_depth--;
if(a_depth <= 0)
{
cargo = "value";
left = NULL;
right = NULL;
}
else
{
cargo = "operator";
left = new Node(a_depth);
right = new Node(a_depth);
}
}
// destructor
Node::~Node() {
delete left;
delete right;
}
The C++ way would be to use smart pointers.
Here you're returning copies of local objects, making temporary objects. Once the make_node call is finished the object don't exist anymore making your pointers dangling.
So don't do that.
Use smart pointers instead to allow the nodes to be freed once unreferenced.