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.
Related
I have a Trie program written in C++. There is an issue with deleting Trie. Even though the code is performing delete operation memory is not getting freed. Can someone point where I am doing wrong? Program doesn't deal with the individual string deletion from Trie. Below is the delete snippet of code.
void deleteTrie(trieNodeT **t) {
if(*t) {
trieNodeT *current = *t;
for(int i=0; i<26; i++) {
if(current->children[i]) {
deleteTrie(¤t->children[i]);
free (current->children[i]);
}
}
}
}
void deleteEntireTrie(trieCDT *t) {
if (t) {
deleteTrie(&t->root);
}
}
Below is the link of entire source code:
https://ideone.com/xL7bvu
Given that this is C++:
(trieNodeT *) malloc(sizeof(trieNodeT));
should be:
new trieNodeT;
You can't use delete and malloc together, it's undefined behavior.
Alternatively, you could replace:
delete current->children[i];
with
free(current->children[i]);
You also probably need to write out null into what you're deleting:
if(current->children[i]) {
deleteTrie(¤t->children[i]);
delete current->children[i];
current->children[i] = nullptr; // or 0
}
Where is the delete for the root node?
You do not need to null the pointer for deletion to take effect. The memory is 'marked' deleted with delete statement. If you do not null the pointer, then the pointer still points to the 'marked' deleted memory area. C++ purists would jump up and say that what I say following is wrong - immediately after a delete, if you access the memory through that old pointer, in many implementations, the data would still be there. Because the memory block was just marked as deleted; NOT physically overwritten. BUT you should never access that deleted memory. The program takes away that marked deleted memory and assigns it away when it next needs memory; and you do not have any control over it. And with multithreading, that memory might be gone even 'immediately'.
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.
I'm new to C++ so bear with me.
I made a struct that looks like this:
struct node{
double startPoint;
double endPoint;
vector<node*> children;
void addChild(node *aNode){
children.push_back(aNode);
}
void addPoints(double start, double end){
startPoint = start;
endPoint = end;
}
};
Down the line in my program, I have the following:
vector<node*> data;
....
node *temp = (node*)malloc(sizeof(node));
temp->addPoints(lexical_cast<double>(numbers[0]), lexical_cast<double>(numbers[1]));
data[index]->addChild(temp);
where "Index" is a index of the vector data. the lexical_cast stuff is taking those numbers from string to doubles.
Everything works until the addChild(temp) line.
The terminal spit this out:
First-chance exception at 0x585b31ea (msvcr90d.dll) in Tree.exe: 0xC0000005: Access violation reading location 0xcdcdcdc1.
Unhandled exception at 0x585b31ea (msvcr90d.dll) in Tree.exe: 0xC0000005: Access violation reading location 0xcdcdcdc1.
But I have no idea how to deal with that.
malloc allocates some space, but doesn't put anything in it. It works fine for plain-old-data structures (or trivially initializable classes), and in C that's all you have.
In C++ you have classes, like std::vector amongst others, which need to be properly constructed in order to establish some invariants. This is done with a straight declaration for objects with automatic storage duration, but for dynamically-allocated objects you need to use new instead of malloc.
For example,
std::vector<int> global; // (1)
void foo() {
std::vector<int> local; // (2)
std::vector<int> *bad = malloc(sizeof(*bad)); // (3)
std::vector<int> *good = new std::vector<int>; // (4)
std::unique_ptr<std::vector<int>> better(new std::vector<int>); (5)
}
is fine - this global is initialized (by which I mean the constructor is called) automatically
is fine - this local variable is also constructed automatically, and destroyed properly as soon as foo exits
you can't use bad for anything, because any method you call will assume the constructor ran already, and it didn't
ok, you can't use bad for anything without explicitly constructing it using placement new. You shouldn't do this though, it's only appropriate where you're doing clever or tricky stuff with custom allocation.
this is ok (but note you have to delete it manually - foo has a memory leak)
this is better - you don't need to clean up manually
Now, note that your node class also has a constructor. In this case, it's automatically-generated, and does nothing but call the vector constructor. Still, you need it to be called, which means using new for dynamically allocating a node.
So, your program should probably look more like:
std::vector<std::unique_ptr<node>> data;
...
std::unique_pre<node> temp(new node);
temp->addPoints(...);
data[index]->addChild(temp);
Note I'm assuming data[index] is valid (I see from addChild you know how to populate a vector already), and that the single-owner model implemented by unique_ptr is appropriate.
As far as the code I see, you never add any nodes into the data array
data.push_back(something);
So accessing data[index] would be out of the allocated memory of the array. It won't complain until you try to set memory in that block (via addChild trying to push an element into the children array).
I would recommend that you store a node instead of a node* in your vector so you don't have to manage the memory on your own.
this is C++ so you don't have to malloc the space for a node you can use new like so:
Node * n = new Node();
New is much better because it calls the constructor and allocates space, whereas malloc just does the latter.
You haven't shown much of your code, but I would restructure the node class like this.
struct node{
double startPoint;
double endPoint;
vector<node> children;
node(){} //add default constrcutor
void addChild(node aNode){
children.push_back(aNode);
}
node & operator=(const node & n) {
startPoint = n.startPoint;
endPoint = n.endPoint;
return *this;
}
node(double start, double end): startPoint(start),endPoint(end){
} //in c++ you have constructors which this should have been in the first place
//constructors are used for initializing objects
};
this is better is that now you can't pass add child nullptr avoiding a lot of problems in your code. You also have a constructor now. Now you can add a node like this.
node temp(start,end); data[index]=temp;
You have a constructor now which addPoints should have been in the first place
I also made an assignment operator
Using the style of coding where you allocate memory on the stack and don't use new is called RAII and is a vital technique for learning c++ and producing exception safe code, this is the main reason I advocate not storing node*'s
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.
#include<iostream>
#include<set>
#include<stdlib.h>
using namespace std;
typedef set<short> pos;
typedef struct tree
{
pos first;
}tree;
class check
{
public:
pos last;
void check_set();
};
void check::check_set()
{
tree *root,p;
root=(tree*)malloc(sizeof(tree));
root->first.insert(2);//SEGMENTATION FAULT HERE WHY???
p.first.insert(3);//NO SEGMENTATION FAULT
}
int main()
{
check obj;
obj.check_set();
obj.last.insert(1);//NO ERROR HERE
return 0;
}
Use new instead of malloc.
malloc only allocates memory, it doesn't initialize it in any way and doesn't construct the objects that will be living in that memory. new on the other had constructs C++ objects. So to get a valid tree object (with a properly initialized first member), use this:
root = new tree();
Later, when you want to release that object, use delete:
delete root;
tree *root,p;
root=(tree*)malloc(sizeof(tree));
root->first.insert(2);//SEGMENTATION FAULT HERE WHY???
p.first.insert(3);//NO SEGMENTATION FAULT
p is allocated on the stack! So it's constructor is called. root's constructor on the other hand is never called! You just allocate a memory of the size a tree would need!
The problem is that root doesn't point to a tree, it points to a tree-sized chunk of allocated memory. Then you try to execute a set operation on an internal member, when the set (with its internal structure and well-groomed pointers) isn't actually in there.
malloc doesn't call the constructor, so neither tree's constructor nor std::set's constructor ever get called and you're trying to populate the unconstructed std::set. That is why you get segfault.
Use new as:
root = new tree(); //this allocates memory, and constructs the object as well.
//deallocation
delete root; //call the destructor, and then deallocate the memory
Or use placement-new as:
root=(tree*)malloc(sizeof(tree)); //only allocates memory
root = new (root) tree; //constructs the object in the memory pointed to by root.
//deallocation
root->~tree(); //call the destructor
free(root); //and then deallocate the memory