Lets say i have a class TwoWayList that holds Records , and GetRec actually creates a new list on the heap, here is the method
void GetRec(TwoWayList<Record> &rec)
{
TwoWayList<Record>* list= new TwoWayList<Record>();
Record r;
list->Insert(&r);
}
Now i have the follow two scenarios, the first one dies when i call delete, and the other one i just get a null reference to record, so when i call MoveToStart() i get a segfault, however if i just delete it works...
int main () {
TwoWayList<Record> record;
GetRec(record);
record.MoveToStart();
delete &record;//crash
return 0;
}
int main () {
TwoWayList<Record> *record;
GetRec(*record);
record->MoveToStart(); //segfault
delete record;
return 0;
}
So whats going on here? Im creating a TwoWayList in the heap in the method, therefore shouldnt i be able to delete (in fact wont it be a leak if i dont delete it?) Whats the correct way to get the TwoWayList from the method here in order for me to be able to delete it later?
Thanks
Daniel
Your first main creates record on the stack -- not the heap. So your attempt to delete the address of a stack variable crashes.
Your second main never allocates record at all. So when you try to use the pointer, it segfaults.
Also, your function allocates memory, but then forgets about it and leaks it. By that I mean that you create a new list, but never hold onto the pointer. Once the function exits, you no longer have a pointer to the list you created -- probably not what you wanted to do.
GetRec also ignores the input parameter -- also probably not what you wanted.
Guessing at what you're attempting...
void GetRec(TwoWayList<Record> &rec)
{
Record r;
rec.Insert(r);
}
int main () {
TwoWayList<Record> record;
GetRec(record);
record.MoveToStart();
return 0;
}
This creates a TwoWayList (named record), passes a reference to record to the function GetRec. GetRec creates a Record and Inserts it into the TwoWayList. Back in main, it calls MoveToStart on record (which now has one Record inserted into it).
This avoids any issues with new/delete by using the stack, at the cost copying Record when you insert it into the TwoWayList. It's doubtful the performance cost of that copy will matter much to you. But if it does, just say so.
void GetRec(TwoWayList<Record> &rec)
{
TwoWayList<Record> *list= new TwoWayList<Record>();
Record r;
list->Insert(&r);
}
Well, you allocate some memory on the heap and let its pointer go out of scope here. You sure you didn't mean to do:
rec = new TwoWayList<Record>(); //rec should really be a reference to a pointer
?
TwoWayList<Record> record;
delete &record;//crash
You cannot delete objects on the stack.
TwoWayList<Record> *record;
GetRec(*record);
record->MoveToStart(); //segfault
delete record;
Here your GetRec isn't changing record, which i assume you wanted. As record points to garbage, a call on that object will obviously break.
In the first example, you are deleting a local variable, which is bad. Not needed; the variable is 'deleted' when it goes out of scope at the end of the function.
Your second example is attempting to use an uninitialized pointer. You need to allocate an instance of TwoWayList<Record> using new.
Also, your GetRec function is allocating a list on the heap and never calling delete, which is causing a memory leak.
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've a fairly complex application written in c++. I've a class called OrderBook. I need to create an array of OrderBook objects dynamically, so what i've done is,
OrderBook* pOrderBooks; // In header file
At runtime, I create the array as
p_OrderBooks = new OrderBook[n]; // n is an integer initialized at run time
The program works fine. But when I try to delete the array (as I need to create a new array pointed by pOrderBooks) the program crashes. This is how i delete it.
delete[] p_OrderBooks;
I've made sure that the crash happen exactly due to that line. So what i'm currently doing is reinitializing the pointer without deleting the previously allocated memory.
//delete[] p_OrderBooks; // <- crash happens here
p_OrderBooks = new OrderBook[k]; // for some 'k'
But it's bad since there'll be a memory leak. I'd like to know how to properly free the memory before re-pointing to the new array.
You are allocating p_OrderBooks but deleting pOrderBooks
If that's just a simple typo in your post, then it is likely that you are overrunning the bounds of this array, writing to elements past the beginning or end, therefore corrupting the heap so it crashes when you try to delete it.
Is it possible that one or more of your destructors for OrderBook is throwing an exception out of the destructor? If so (typically considered bad) and if it is not handled will crash your application.
I found the issue. I'm passing a pointer to an object created in the base class to OrderBook objects.
Server* p_Server = new Server(); // Some class
...
pOrderbook[i]->SetServer(p_Server) // <- for i=[0:99]
Passed p_Server is stored in OrderBook objects as p_ServerBase (say).
Server* p_ServerBase; // <- in OrderBook.h
...
OrderBook::SetServer(Server* pServer)
{
p_ServerBase = pServer;
}
Then in the OrderBook's distructor i'm trying to delete that, p_ServerBase, which is still being used in the base class.
...
~OrderBook()
{
delete p_ServerBase;
}
Haven't had that experiance before. I' won't do that again :)
If you are doing something like this:
OrderBook* p_OrderBooks;
int n;
p_OrderBooks = new OrderBook[n]; // here n contains garbage
cin>>n
delete[] p_OrderBooks;
Here n can be any garbage value, we don't know its size ,and perhaps we start accessing memory that we don't own. It could be problematic.
You should take input first
cin>>n
p_OrderBooks = new OrderBook[n];
I've implemented a heap using two classes called IndexedHeap and HeapEntry. I have some corrupt memory access causing segfaults and I believe I know where/why, but I'm not sure how to fix it. Here's how I've designed the classes so far:
class IndexedHeap
{
private:
std::vector<HeapEntry*> heap; // the entries held by this heap
public:
...
};
class HeapEntry
{
private:
int index;
size_t priority;
unsigned long long key;
IndexedHeap* myHeap; // reference to heap where this entry resides
public:
HeapEntry(unsigned long long key, size_t priority, IndexedHeap* myHeap)
: key(key), priority(priority), index(-1), myHeap(myHeap)
{}
};
Both the heap and its entries need to refer to each other. As you can see I've decided to use a raw pointer to an IndexedHeap in HeapEntry. This is where I think I went wrong, but I'm not sure.
Throughout program execution, new heap entries are created as part of one heap. Entries are also removed from this heap and destroyed. Perhaps when one heap entry is destroyed, the heap it points to gets corrupted. That would explain my memory issues, because the next time a heap entry tries to access its heap, it accesses memory that has been released.
Unfortunately I'm not convinced of that. I haven't implemented a destructor for HeapEntry. The default destructor just calls destructors for all instance variables of a class right? So wouldn't the pointer to myHeap get destroyed, while the heap object itself survives?
So, what is the correct way of designing this kind of relationship, and can my memory issues be explained from the code I've posted? Thanks, and please let me know if you'd like to see more code or more details.
Code that creates and destroys entries on the heap:
HeapEntry* IndexedHeap::insert(unsigned long long key)
{
HeapEntry* entry = new HeapEntry(key, 1, this);
heap.push_back(entry);
int index = heapifyUp(heap.size() - 1);
heap[index]->setIndex(index);
return entry;
}
void IndexedHeap::deleteAtIndex(int pos)
{
if (pos >= 0 && pos < heap.size())
{
// Copy heap.back() into the position of target, thus overwriting it
*heap[pos] = *heap.back();
// Fix the index field for the just copied element
heap[pos]->setIndex(pos);
// We've removed the target by overwriting it with heap.back()
// Now get rid the extra copy of heap.back()
// Release the mem, then pop back to get rid of the pointer
delete heap.back();
heap.pop_back();
// Heapify from the position we just messed with
// use heapifyDown because back() always has a lower priority than the element we are removing
heapifyDown(pos);
}
}
Well, firstly, why arent you using the priority queue from STL, or using a multimap as a priority queue? Its a better solution than writing your own.
Next, the code structure: std::vector<HeapEntry*> heap; is notorious for leaking memory, with people not deleteing the memory pointed to, while and for causing serious memory faults when people try to delete the pointed memory and get that deletion wrong.
The "IndexedHeap* myHeap;" is most likely not your problem. References to things you dont own can be an issue if someone deletes those objects, but chances are you have stopped using th entries by then. Btw, since its a reference, you should consider making it a reference (which is then bound during ctr and never changed) - but that wouold alter the safety of the code in anyway. As youbelieve, the dtr for a pointer does nothing to the target.
Can you run valgrind? it solve things like this very quickly. Else:
Try not deleting any Entries, and see if that stops your faults, if so its telling.
You could also try tracking the pointers you new and delete, either by prints, or by a global set/map object. This can be handy to find these things.
Tutorials, searches, and the dim memory of my C++ formal education have left me clueless as to where I should use delete when I'm using a dynamically allocated object pointer in a loop, such as:
// necessary files are included, this code is within main
T * t;
t = foo.getNewT();
while (!t->isFinalT()) {
// print t stuff
delete t; // is this where I should delete t?
t = foo.getNewT();
}
delete t;
This lack of knowledge has become particularly troublesome on a recent class project. On my laptop (Linux Mint, g++ Ubuntu/Linaro 4.7.3-1ubuntu1) the code ran fine without the delete statement and crashed when I added the delete statement. On the school server (Solaris, g++ (GCC) 3.4.5), the code segfaulted after a few iterations without the delete statement, and runs fine when I add the delete statement.
How do I handle this kind of loop properly so that it will run in most environments?
Additional Info:
The error on my laptop occurs when the program reaches the delete request:
*** Error in 'program': free(): invalid next size (fast):...
Some of the other code:
// T.h
class T {
int id;
int num;
int strVarPos;
char * strVar;
public:
T();
~T();
// + misc. methods
}
// T.cpp
T::T() {
id = 0;
num = -1;
strVarPos = 0;
char * strVar = new char[11];
strVar[0] = '\0'
}
T::~T() {
delete [] strVar;
}
// Foo.cpp
T * Foo::getNewT() {
T * t = new T;
// populate T's fields
return t;
}
Resolution:
Because a simple test with just T * t and the loop worked ok, I ended up reconstructing the project starting from blank and adding one class at a time, to see when the problem would appear. Turns out that I had added additional content into a dynamically allocated array elsewhere in the program without updating the size constant I was using to initialize the array.
Evidently the school server could only handle the resulting memory discrepancy without crashing if I was making sure to delete the pointers properly (the program didn't run long enough to cause a significant memory leak in my tests), while my laptop wouldn't notice the memory discrepancy until I attempted to call delete (and then would crash).
Assuming that foo.getNewT() is handing ownership of the memory over to the caller:
T * t;
t = foo.getNewT();
//while (!t->isFinalT()) // if foo.getNewT ever returns NULL, this will be UB!!!
while (t != nullptr && !t->isFinalT())
{
// ...
delete t; // if you now own it and are no longer going to use it, yes, delete it here
t = foo.getNewT();
}
delete t; // you also need this one to delete the "final" t
However, you can avoid having to do it yourself by using std::unique_ptr:
std::unique_ptr<T> t;
t.reset(foo.getNewT());
while (t && !t->isFinalT())
{
// ...
t.reset(foo.getNewT());
}
Alternatively, you could rewrite the loop to flow a bit better:
std::unique_ptr<T> t;
do
{
t.reset(foo.getNewT());
if (t)
{
// do stuff with t
}
} while (t && !t->isFinalT());
the code ran fine without the delete statement and crashed when I
added the delete statement.
Are you sure getNewT is handing ownership of the T* to you? If you delete it, and then it tries to delete it later, you will end up with a heap corruption. If it is handing ownership over to the caller, and you do not delete it, you get a memory leak.
With the additional information in your edit:
char * strVar = new char[11];
That line is unnecessary if you declare strVar as either a std::string or a char[11]. If you attempt to copy any of those T objects, you'll be using the default copy constructor (as you have not defined one), which will do a shallow copy (that is, copy the value of the pointer for strVar). When you delete 2 Ts that are both pointing to the same memory location, you get a heap corruption. The most robust solution would be to declare strVar as a std::string.
The problem is not the delete. You have put it in the right place. It's more likely something else you are doing that is causing undefined behaviour.
Note that you should have a delete t after the loop as well (to catch the last one). This is assuming that foo.getNewT() always returns a valid pointer (which it must, because you never check if it is NULL).
You should delete a dynamically allocated memory when you no longer need it. If you want t to hold its value inside the for loop, then delete it outside the loop otherwise delete it inside.
However, the best thing to do is to use std::unique_ptr when you really have to use pointers . It will take care of deallocating the memory itself when all references to the memory are destroyed. You should try to avoid allocating memory as much as you can. Use STL containers if they fit the job.
I think when you delete t you are deleting the real object inside your structure.
Maybe that what is causing the problem.
I would like to ask if I's correct the following :
MyClass *obj = new MyClass();//allocate memory
obj.Variab="HELLO";
obj=NULL;
delete obj; //free memory
Is the memory allocated for obj deleted after the last two sentences? Appreciate.THX
I would like to mention that I am working in c++ /Ubuntu. G++ is the compiler
EDIT:
What if I have?
int i=0;
list<string>l;
while (i<100)
{
MyClass *obj = new MyClass();//allocate memory
obj->Variab="HELLO";
//add the obj.valie in a list
l.push_back(obj);
i=i+1;
delete obj; //free memory
}
it is ok?
no, you should use delete before assigning to NULL
delete obj; //free memory
obj=NULL;
this is becasue the actual parameter to delete is the address of the allocated memory, but if you assign NULL before delete is used, you are actually passing NULL to delete, and nothing will happen, and you will get yourself a memory leak.
your edit question:
this code will not compile, as obj is not defined outside the while scope, in any case, also, l is a list<string> and you are trying to insert MyClass* types,this will result in another compilation error. also, you should use obj->Variab and not obj.Variab, since obj is a pointer.
EDIT to EDIT:
well, you still got a compilation error, since obj is not defined when you are trying to delete it. try this:
#include <iostream>
#include <list>
using namespace std;
class MyClass {
public:
string Variab;
};
void myfunction (const string& s) {
cout << " " << s;
}
int main()
{
int i=0;
list<string>l;
while (i<100) {
MyClass *obj = new MyClass();//allocate memory
obj->Variab="HELLO";
l.push_back(obj->Variab);
i=i+1;
delete obj; //free memory
}
for_each (l.begin(), l.end(), myfunction);
}
This not correct:
obj = NULL; // don't do that!
delete obj;
When you assign NULL to obj, you're losing the address it contained before, leaking the memory. When you then delete obj, you are deleting NULL, which is well-defined - as doing nothing.
As others have said,
delete obj;
obj = NULL;
is the common pattern to do that.
However, I consider it an anti-pattern.
Whenever you are tempted to assign NULL to a pointer after deleting its content, ask yourself: Why is this pointer still in scope? Are you sure you still need it?
It's much better to simply let a pointer fall out of scope once it's done.
Whenever you are doing
resource r = acquire();
use(r);
free(r);
(with memory/dynamically allocated objects being the most common resource), alarm bells should go off. What if use(r) fails with an exception?
Never use naked, dumb pointers. Better read about RAII and smart pointers.
This would leak, delete will not clean up what you allocated with new. Change the order:
delete obj;
obj = NULL; // I would avoid this.
Setting obj to null does not free the memory you allocated. The memory becomes no longer assigned to a variable but is still reserved, and results in a memory leak. Calling delete on a null pointer will have no effect. After the memory has been freed, the pointer becomes invalid and it is good practice to assign it to null. You need to switch the order of the last 2 statements:
delete obj; //free memory first
obj=NULL; //Set pointer to null for safety
You have to delete the very same address as was returned by new - so you have to first delete, then set to null.
Setting pointer to null doesn't affect allocation - you just overwrite the address stored in the pointer and can't access the object anymore (which implies you can't delete the object and have it leaked).