How do i free up memory occupied by a tree? - c++

Each node in my tree has M children. Some of them may be NULL. After I get done with the tree I am recursively going through each element of the tree and deleting it but that does not free up memory used by the program. First I tried this without defining destructor and then after defining destructor too doesn't help. Please tell me where I am wrong in freeing up memory space. My code for deleting tree is as follows:-
void deleteTree(node* s)
{
if(s==NULL)
return ;
else
{
for (int i=0 ; i < M ; i++)
{
deleteTree(s->child[i]);
}
delete(s);
}
}
A node contains a string vector ,array of integers and array of pointers to its children.
struct node
{
vector<string> stateBoard;
int Nstate;
int *NstateAction;
node** child;
int depth;
double Q;
double *Qvalue;
node()
{
Nstate=0;
depth = 0;
NstateAction = new int[M];
Qvalue = new double[M];
child = new node *[M]; //
for( int i=0 ; i < M ; i++)
{
NstateAction[i] = 0;
child[i]=NULL;
}
}
~node()
{
stateBoard.clear();
vector<string>(stateBoard).swap(stateBoard);
}
};

Just delete it. The part that deletes the children of a node should be in the destructor of the node class, not outside. If you don't put it there, deletion isn't recursive, so you will leak grandchild nodes and their subtrees.

If you want to get really technical and practice your C++ 11 I would suggest using smart pointers. Just to be clear I would put all destruction mechanisms to the destructor but smart pointers are a great thing to c++ so as practice you should use them.
So you should declare something like this:
//don't forget to #include<memory>
std::unique_ptr<int> NstateAction;
//don't use vectors as arrays, if the standard library has an alternatve you should use it
std::vector<unique_ptr<int>> child;
std::unique_ptr<double> QValue;
Smart pointers are pointers that automatically release memory when they go out of scope so this should do the trick.
Now using smart pointers is a bit tricky but here is a question that will help:
c++ - How can i initialize a smart point using a naked new?
Just go to the answers.

Related

How to delete dynamically allocated struct consisting dynamically allocated array member in C++?

I am doing my homework which requires me to implement a Trie Tree without using vector. I have a struc defined as following:
typedef struct{
char _name;
int32_t * _children;
int32_t _children_size;
int32_t _children_capacity;
int32_t * _location;
int32_t _location_size;
int32_t _location_capacity;
} TrieTreeNode;
To reduce the memory use, I store all the pointers of TrieTreeNode into a global variable TrieTreeNode ** nodes_array. Then the _children member of each TrieTreeNode is just an array whose elements are int32_t indices to nodes_array.
For example, say we have TrieTreeNode * parent. To access its first child, we use nodes_array[parent -> _children[0]].
My question is how to delete the whole Trie Tree? I have tried the following approach (tail is the number of pointers nodes_array has):
void delete_node(TrieTreeNode *node){
delete [] node -> _children;
delete [] node -> _location;
}
void delete_tree(){
for (int i = 0; i < tail; i++){
delete_node(nodes_array[i]);
}
delete [] nodes_array;
nodes_array = NULL;
}
However, when I used both -ps -l command and GDB to monitor the memory use of my program before and after deleting a tree, the memory only decreases a little bit. The RRS goes from 13744 to 13156, while it is only 1072 before I build the tree.
Any suggestions will be appreciated!
You are not deleting the nodes, only the pointers within each node.
Consider this:
void delete_tree(){
for (int i = 0; i < tail; i++){
delete_node(nodes_array[i]);
delete node_array[i]; // Delete the node itself.
}
delete [] nodes_array;
nodes_array = NULL;
}
After calling delete_node to free the two pointers in each node, you should then delete the node itself delete node_array[i] to free up the remaining memory for each node.
Personally though, I am a fan of defining constructors and destructors for structures so that I don't have to remember to initialize everywhere I create them or do the extra deletion everywhere I might dispose of one.

Deleting linked objects

I have two classes: "node" and "poly". The node objects are linked together to form a linked list. The poly object holds a pointer to the first node. I am trying to deallocate the memory for the entire "poly". I want to delete the poly - then within the poly destructor call a function (something like "freePoly") that will help me iterate through the entire linked list of node objects - deleting all nodes.
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");
//???
}
class poly
{
private:
Node *start;
public:
poly(Node *head) /*constructor function*/
{
start = head;
}
~poly() /*destructor*/
{
//???
}
void freePoly();
};
void poly::freePoly()
{
//???
}
I've tried a lot of things, but essentially I get stuck where I'm only deleting the first node object. Then I've lost the pointer to the other nodes... and leak memory because I can't access them anymore for deletion.
You can avoid a lot of problems and work by using a std::vector instead of a Do-It-Yourself linked list. Unless this is for learning.
That said, do
~poly() /*destructor*/
{
while( start != 0 )
{
node* p_doomed = start;
start = start->next;
delete p_doomed;
}
}
There are also many other ways to do this, but the above is a pattern that can help you figure out how to do similar things.
If you want to keep your code as is, then your freePoly should look like this:
while(start)
{
Node *ptr = start;
start = start->getNext();
delete ptr;
}
Notice what this code does: first it makes a copy of the pointer to the current head - i.e. the first Node, then it makes head point to the next object and only then calls delete for the old head pointer.
Of course, this design isn't ideal: you are programming using a C++ compiler and you have some classes and some member functions but you aren't really using C++ effectively:
Not only does language provides you with wonderful tools such as std::list or std::vector so that you don't have to reinvent the wheel and things like std::unique_ptr so that pointers know when it's safe to delete themselves.
It also provides you with powerful abstract concepts to model the bahavior of objects.
I suggest that you take a step back and rethink your code. Key questions to ask are: how can I write less code here? What facilities of C++ can I leverage here? What are these objects I have and what does each object do?
I understand that this may be a homework exercise and you have to implement things a certain way, but don't let that stop you from learning.
You could try this:
private:
void auxDestroy(Node* p);
void Node::auxDestroy(Node* p){
if (p!=0) {
if (p->next != 0) {
auxDestroy(p->next);
}
else {
delete p;
}
}
}
Then in the destroy method you could call this auxDestroy(this->next);
~Node(){
auxDestroy(this->next);
}
And in poly destructor:
~poly(){
delete this->start;
}

Memory Management Confusion C++

I'm having trouble understanding some basic memory management principles in C++. This code is part of a loop that is part of a function that reads in a maze file into a 2D vector.
According to Valgrind, the following code is causing memory leaks...
Note that t is a MazeNode object and verts is a vector within the t class that holds pointers to node objects (not to be confused with MazeNode objects):
node* top = new node(TOP, rowCount, i, t.type);
node* bot = new node(BOTTOM, rowCount, i, t.type);
node* left = new node(LEFT, rowCount, i, t.type);
node* right = new node(RIGHT, rowCount, i, t.type);
t.verts.push_back(top);
t.verts.push_back(bot);
t.verts.push_back(left);
t.verts.push_back(right);
temp.push_back(t);
top = NULL;
bot = NULL;
left = NULL;
right = NULL;
delete top;
delete bot;
delete left;
delete right;
Initially I did not set each of the pointers to NULL before deleting them, but would get allocation errors. So I just set them to NULL and my code works. I guess I'm just really confused why this would cause memory leaks and why I would need to set the pointers to NULL. There is probably a way easier non-pointer way to do this, but maybe this problem will help me understand memory management better.
Thanks everyone.
EDIT: Here's the MazeNode class (which is what 't' is) (also excuse my lazyness in writing this class, making everythign public like a struct)
class MazeNode
{
public:
void setType(char c);
char getChar();
NodeType type;
vector<Direction> visitedFrom;
vector<node*> verts;
};
And the node class:
class node
{
public:
node();
node(Direction d, int r, int c, NodeType t);
~node(); //empty definition
node(const node* n);
node& operator=(const node& n);
void addAdj(node* a, int w);
void printAdj() const;
string direction() const;
void print() const;
bool operator<(const node& n) const;
int distance; //from start
bool visited;
node* prev;
vector<Edge> adj;
Direction dir;
int row, col;
NodeType type;
};
EDIT2: Thanks everyone. I understand the problem now. I changed my vectors of pointer objects so that I wasn't using pointers anymore.
Prior to adding the null assignment, your code had a problem different (worse) than a memory leak: storing and probably also using a stray pointer, that is, a pointer pointing into de-allocated memory.
Making it a memory leak by adding the null assignment makes it better, but not much.
The real solution is not to keep any pointers anywhere after you have called delete on them.
That is, do not push_back or do not delete here.
You are placing the pointers into a container, then deleting the pointers. When your code later tries to use those pointers they are invalid and cause a crash.
By setting the pointers to NULL before you delete them, you end up not deleting them at all - deleting a NULL pointer doesn't do anything. But now there's nothing to delete the objects later, and you get a memory leak.
You need to find some spot in the code where you're not using the pointers anymore, and delete them there.
Edit: Of course I should have mentioned that a smart pointer such as std::shared_ptr eliminates this hassle altogether, because it deletes the object automatically.
You are setting the values to NULL before deleting them, so you are trying to delete NULL and nothing is being deleted. Try moving the delete calls above the NULL calls.
This confusion is exactly why I create a macro for these kind of things:
#define delobj(obj) (delete obj, obj = NULL)
And you would use it like this:
delobj(top);
delobj(bot);
delobj(left);
delobj(right);
The error is using the vector of pointers. According to you, verts is this:
vector<node*> verts;
But what it should be is this:
vector<node> verts;
In the first case, when you push_back() the pointer, that's OK, but when you pop_back or otherwise re-size the vector, the pointer is the "contents" of the vector, and is de-allocated, but not what the pointer points to, which is the node. Hence the node leaks. But in the second case, the node is "part" of the vector, and is allocated/deallocated as part of re-sizing the vector.
Your pattern here probably indicates a Java/C# background, as "new-ing" into a container is very very common in those languages, but to do that in C++, you need a container of smart pointers (like vector<shared_ptr<node>> or something), which is probably beyond the scope of the question. But in those languages, every reference to a reference type is a "smart pointer" (more or less) and so this is done automatically. C++ isn't like that.
You either need to change your code to use a vector<node> (and change how you're pushing back on to it) or you need to explicitly de-allocate your nodes when the vector shrinks.
Change to:
delete top;
delete bot;
delete left;
delete right;
top = NULL;
bot = NULL;
left = NULL;
right = NULL;
And it should work.

A question about memory leaks

#include <QList>
class MyType{
//This has some data in it....
};
QList<MyType> f()
{
QList<MyType> list;
for(int i = 0; i<10; i++ )
{
MyType* item = new MyType();
list << *item;
}
return list;
}
QList<MyType> temp_var = f();
When temp_var goes out of the scope and destroys, what happens to the items that we created and add to this list?
Is there going to be any memory leaks?
Thank you.
Yes, there will be a memory leak. As a general rule, you must have one delete for each new in your program.
In your specific case, the faulty logic happens much earlier than temp_var's destruction. You allocate the items, and then store a copy of those items in the list. You should immediately destroy the original, no-longer-useful items.
Your for loop could be :
for(int i = 0; i<10; i++ )
{
MyType* item = new MyType(); // get me an item.
list << *item; // put copy of item in list
delete item; // destroy my item
}
When expressed that way, it is obvious that we shouldn't use new at all!
for(int i = 0; i < 10; i++)
{
MyType item;
list << item;
}
This version won't leak, assuming that MyType doesn't have any memory-management bugs of its own.
EDIT: As an aside, had your program been:
QList<MyType*> f() // List of POINTERS
{
QList<MyType*> list;
for(int i = 0; i<10; i++ )
{
MyType* item = new MyType();
list << item; // Storing a POINTER
}
return list;
}
Then, yes, you would have had precisely the memory leak you expected. QList does not automatically provide delete on pointer types.
I don't see any point of using new in your code, as you're not storing the pointers in the list, rather copies of the object created with new, and you're not deleteing it. So yeah, there is memory-leak in the function itself.
Seeing that QList is not a list of pointers, I can say that you shouldn't use new in your code:
QList<MyType> f()
{
QList<MyType> list; //note : its not a list of MyType*
for(int i = 0; i<10; i++ )
{
MyType item; //automatic variable
list << item;
}
return list;
}
When a QList gets destroyed / goes out of scope, it destroys its content with it. In your case, the content is made of copies of your objects (built from the implicit copy-constructor), not the objects themselves. The memory will leak in each iteration of the for-loop since the original object created by new MyType() will lose its pointer, but will remain allocated.
There certainly will be a leak if it you don't delete all of those items you created with new MyType()!
In the destructor for QList you need to go through the list and call delete on each of those items.

stl + memory management question

For example, i have next code:
#include <set>
using namespace std;
struct SomeStruct
{
int a;
};
int main ()
{
set<SomeStruct *> *some_cont = new set<SomeStruct *>;
set<SomeStruct *>::iterator it;
SomeStruct *tmp;
for (int i = 0 ; i < 1000; i ++)
{
tmp = new SomeStruct;
tmp->a = i;
some_cont->insert(tmp);
}
for (it = some_cont->begin(); it != some_cont->end(); it ++)
{
delete (*it);
}
some_cont->clear(); // <<<<THIS LINE
delete some_cont;
return 0;
}
Does "THIS LINE" need to be called before deleting some_cont for avoiding memory leaks or destructor will be called automatically?
You don't need to call it, destructor will be called for sure.
No, there is no need to clear the set before destroying it.
Note that there is very rarely a need to allocate an std::set (or any standard container) manually. You'd be much better off just putting it in automatic storage and letting C++ handle the cleanup for you:
So instead of
set<SomeStruct *> *some_cont = new set<SomeStruct *>;
use
set<SomeStruct *> some_cont;
then change all some_cont-> to some_cont. and remove the delete some_cont (the container will be destroyed when main exits automatically.
The advantage to do things this way are:
You don't need to remember to delete the container, and
You don't need to do an expensive memory allocation up front.
It's also far more idomatic C++ to put things in automatic storage.
No, you don't need to explicitly clear a set before destroying the set.
OTOH, you do have a number of other problems ranging from lousy (Java-like) design, to incorrect syntax, to a missing operator to lots of potential memory leaks. While some of the design might make sense in Java or C#, it's a really poor idea in C++. Once we get rid of the most egregious problems, what we have left is something like this:
#include <set>
struct SomeStruct
{
int a;
SomeStruct(int i) : a(i) {}
bool operator<(SomeStruct const &other) const { return a < other.a; }
};
int main ()
{
std::set<SomeStruct> some_cont;
for (int i = 0 ; i < 1000; i ++)
{
SomeStruct tmp(i);
some_cont.insert(tmp);
}
return 0;
}
No it is not, this will be done automatically in the set's destructor.
The STL containers automatically free any memory they own. So in your case the place allocated to store your SomeStruct* will be freed by the destructor of set. Note that the destructor of set does not call any destructors of SomeStruct, so it's good you iterate over them to delete them yourself.