I've an abstract class called GameState which looks like this,
#ifndef GAMESTATE_H
#define GAMESTATE_H
#include <iostream>
class GameState
{
public:
virtual ~GameState(void) = 0 { std::cout << "~GameState" << std::endl; };
virtual void init (void) = 0;
virtual void update (void) = 0;
virtual void shutdown (void) = 0;
private:
};
#endif
In main.cpp,
// Lv1Stage and Lv2Stage is derived class from GameState class.
GameState* lv1Stage = new Lv1Stage
GameState* lv2Stage = new Lv2Stage
// This adds states to state vector which is in gameStateManager.
gameStateManager.addState(lv1Stage);
gameStateManager.addState(lv2Stage);
while(gameStateManager.getType() != ST_QUIT)
{
gameStateManager.update();
}
When I quit the game(when I get out of the loop), I gotta release memories that I allocated to GameState. So I made a function in GameStateManager, called clean, which looks like this.
void GameStateManager::clean(void)
{
while (!_states.empty())
{
//first, release all memories of each states.
_states.back()->shutdown();
//and then, clear memory of state..
_states.pop_back();
}
_states.clear();
}
The reason that I made this clean function is, I don't want to delete all of game states I add every single time, like,
delete lv1Stage;
delete lv2Stage;
delete lv3Stage;
...
So I put clean() function in destructor of gameStateManager, but it seems not working since I detected memory leak.
But the thing is, when I delete all the states myself like above code, memory leak is not detected. However, it causes unhandled exception (my guess is because _states is null cuz I deleted it manually).
So, in conclusion,
- I used clean function to de-allocate memories of vector components(which is game states) in destructor.
But it seems not working (memory leak)
However, deleting all memories myself is bothering me.
Can you guys give me some solutions or, what am I missing?
Your vector holds GameState* pointers to objects that are allocated with new. They must be freed with delete. So, you need to add that, eg:
_states.back()->shutdown();
delete _states.back(); // <-- add this!
_states.pop_back();
If you are using C++11 or later, you can change your vector to hold std::unique_ptr<GameState> objects instead of raw GameState* pointers, and then delete will be called automatically for you when you remove objects from the vector.
Related
Let's assume I got an abstract class ("Book" in the example below) and some derived classes ("ElectroniBook","CodingBook" in the example below). I also want to keep a vector of books in a third class ("Library") and some maps to find them. Let's also assume that I need to create the "Library" from somewhere else using the "addBook" method and then assign it in the main.
Since Book is abstract I eventually need to delete the "Book" pointers I created and I want to do it in some destructor. Neverthless, whenever I try to use delete i got this error message
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
and if I try to replace raw pointers with shared_pointers or unique_pointers I immediately get errors at compile time telling me I'm trying to use pointers that have already been deleted. Note that I'm using C++ 11.
Here's some code just for example :
class Book{
public:
Book(string name, int Npages);
virtual ~Book();
virtual void displayBook() = 0;
private:
string _name;
int _Npages;
}
class ElectronicBook : public Book{
public:
ElectronicBook(string name, int Npages);
~ElectronicBook();
void displayBook() { //do something
};
}
class CodingBook : public Book{
public:
CodingBook(string name, int Npages);
~CodingBook();
void displayBook() { // do something else
};
}
class Library{
public :
Library();
~Library(){
// this doesn't work for me
// for(auto & a : _books)
// delete a;
// _books.clear();
//
//for(int i=0;i<_bookmap.size();++i)
// delete bookmap.at(i);
};
void addCodingBook(string name, int Npages){
CodingBook* cb = new CodingBook(name, Npages);
_books.push_back(cb);
_bookmap[name] = cb;
//should I delete anything here?
};
void addEletronicBook(string name, int Npages){
ElectronicBook* eb = new ElectronicBook(name, Npages);
_books.push_back(eb);
_bookmap[name] = eb;
//should I delete anything here?
};
private :
vector<Book*> _books;
map<string, Book*> bookmap;
}
// separeted function
Library createLibrary(){
Library L;
while(...){
//read books from somewhere(file, input or whatever) and
// addElectronicBook(...)
// addCodingBook(...)
}
return L;
}
int main(){
Library myLibrary = createLibrary();
// do something with Library
}
Since I did several times "new" to add Books, I need to delete them. I tried to do it in the Library destructor like I showed but I got the error mentioned before.
If I understand correctly your issue, you are freeing twice the same memory:
// for(auto & a : _books)
// delete a;
// _books.clear();
//
//for(int i=0;i<_bookmap.size();++i)
// delete bookmap.at(i);
Both _books and bookmap contain pointers that are pointing to the same ares of memory and you are freeing them twice.
When working with raw pointers you have to decide who is the owner of the memory, say, for example _books and who has simply access to the memory but is not responsible for the cleanup.
So, you should:
delete only once, so use only one of the two for loops, say for the sake of argument _books
make sure that the other non-owning structures, say bookmap in our example, never, ever access the memory (i.e. de-reference the pointer) after the deletion
Suggestion: put in the vector unique_ptr so the vector is the owner and put raw pointers in the map to signal that the map is not owning. unique_ptr will take care of cleaning up the memory for you. If you want to be sure, add some print statements or put break points in the destructors if you have a debugger.
Consider the following contrived example:
class AllocatedClass {
public:
AllocatedClass() : dummy(0) {}
private:
int dummy;
};
class AllocatingClass {
public:
AllocatingClass() : list() {}
~AllocatingClass() {
// CANNOT delete the elements in list here because there may
// be more than on instance of AllocatingClass sharing the same
// static list
}
AddNewObject() {
list.push_back(new AllocatedClass());
}
private:
static std::vector<AllocatedClass*> list;
};
In implemetation file
std::vector<AllocatedClass*> AllocatingClass::list;
Putting aside whether multiple instances of a class should share a list of dynamically allocated objects is a good idea, is there a way clean up these new'ed AllocatedClass objects at the end of the program? Does it matter if these never get deleted considering I don't want to delete them until application end?
If the lifetime of the object is the lifetime of the execution of the program then there is no need to free the memory with code. The memory will be free automatically.
Many Linux command line tools do not free their memory in code for performance reasons. (Faster to automatically free pages of memory, than to free each object one by one.)
Another strategy is to keep a separate list of unique AllocatedClass instances, then free them from that list later on (switching ownership of the objects). Like std::list<AllocatedClass*> to_be_freed.
is there a way clean up these new'ed AllocatedClass objects at the end
of the program?
One solution is to use std::shared_ptr and have the deallocation done automatically.
#include <memory>
#include <vector>
#include <iostream>
class AllocatedClass
{
public:
AllocatedClass(int n = 0) : dummy(n) {}
~AllocatedClass() { std::cout << "I am being destroyed" << '\n'; }
private:
int dummy;
};
class AllocatingClass
{
public:
AllocatingClass() {}
void AddNewObject(int num = 0)
{ shared_list.push_back(std::make_shared<AllocatedClass>(num)); }
private:
static std::vector<std::shared_ptr<AllocatedClass>> shared_list;
};
std::vector<std::shared_ptr<AllocatedClass>> AllocatingClass::shared_list;
AllocatingClass ac;
int main()
{
ac.AddNewObject();
ac.AddNewObject(1);
}
Live Example
Note that the destructors are called automatically for the objects that were placed in the vector.
(BTW, it isn't a good idea to name your member variable list).
Most of the time(very close to all the time) an object that creates dynamically allocated objects should have a programmer defined destructor to free the memory when the object reaches the end of its life. AllocatingClass should have a destructor because you allocate dynamic memory with new.
~AllocatingClass() {
for (int i = 0 ; i < list.size();i++) {
if(list[i] != NULL) {
delete list[i];
list[i] = NULL;
}
}
This should both provide a method for de-allocating memory and safety so that you do not delete an already deleted pointer.
I'm very cautious about memory leaks, so I thought I'd have this verified. In the following example would there be a memory leak? My gut instinct says yes.
class Handler // Class definition
{public:
~Handler();
int* ptrToInts;
};
Handler::~Handler() // Class destructor
{
delete[] ptrToInts;
}
Handler handler; // Global object
void aFunction()
{
handler.ptrToInts = new int[20];
}
int main()
{
bool quit = false;
while(!quit)
{
aFunction();
}
return 0;
}
Would ptrToInts be creating 20 separate new ints in separate memory on the heapeach time?
Also, another question is if it weren't for the destructor, would the dynamically allocated memory be freed? Seeing as though the lifetime of the class is the duration of the program, would it do cleanup of all the "new" memory?
Edit: Thanks for the answers. The reason I'm asking this is because I'm trying to get around calling new and delete every time WndProc is called for Raw Input basically, which is how the MSDN tells you to do it. Seems very inefficient.
As soon as you re-assign your pointer without using delete[] to de-allocate that allocated memory on the heap, you create a memory leak. This will happen if you loop your aFunction() as it re-assigns the pointer every time it is called.
As for your second question, your destructor will only delete[] the last array assigned to the pointer.
Only delete[] frees the memory that was allocated by new. And every time you use new, you need a delete.
For the other question, based on the Documentation:
MyClass * p1 = new MyClass[5]; // allocates and constructs five objects
Yes, there is a memory leak when you call the function more than once, without explicitly deallocating handler.ptrToInts after each call;
void aFunction()
{
handler.ptrToInts = new int[20];
}
//-----somewhere we see the caller
while(!quit)
{
aFunction();
}
However, this is a trivial case of detecting leaks... You should learn to use Leak detectors and static analyzers.
See How do you detect/avoid Memory leaks in your (Unmanaged) code?
Of course there is a memory leak. You allocate the ints in
void aFunction()
{
handler.ptrToInts = new int[20];
}
without deallocating the old ints first, like
void aFunction()
{
delete [] handler.ptrToInts;
handler.ptrToInts = new int[20];
}
would do.
Calling aFunction() will lead to "infinite" memory allocations.
And your destructor, which only frees the last allocated ints, even is never called.
Why is your handler not managing it's own memory?
It's very bad practice to allocate memory outside of your object and free it inside or vice versa.
Why not implement the Handler class this way:
class Handler
{
public:
Handler();
~Handler();
void aMethod();
private:
int* ptrToInts;
};
Handler::Handler() {
handler.ptrToInts = new int[20];
}
Handler::~Handler() {
delete[] ptrToInts;
}
void Handler::aMethod() {
delete[] ptrToInts;
handler.ptrToInts = new int[20];
}
int main() {
bool quit = false;
Handler handler;
while(!quit) {
handler.aMethod();
}
}
I would like experts review on the following dynamic memory allocation process and suggest whether there are any memory leaks. Following code is not real code in use, but trying understand concept of memory allocations and de-allocation in different ways.
class ObjMapData
{
private:
int* itsMapData;
........
public:
ObjMapData();
~ObjMapData(){if(itsMapData!= NULL) delete[] itsMapData;}
ClearMemory() {if(itsMapData!= NULL) {delete[] itsMapData; itsMapData= NULL}}
.......
void SetMapData(int* ptrData) { itsMapData = ptrData;} // or should I use int*&ptrData??
int* GetMapData() const { return itsMapData;}
}
Now can I do the following without any memory leaks?
bool Function1(ObjMapData& objMyMap)
{
//populate the ptrData with some data values using many different ways
int* ptrData = new int[1000]; // usually a variable from binary file header
......................
objMyMap.SetMapData(ptrData);
//don't want to delete the memory yet
return true;
}
bool Function2(ObjMapData& objMyMap)
{
int* ptrData = objMyMap.GetMapData();
//do some work such as writing updated data into a binary file
}
bool Function3(ObjMapData& objMyMap)
{
//populate the data
bool bStatus = Function1(objMyMap);
int* ptrData = objMyMap.GetMapData();
//update the map data using ptrData variable
..........
bStatus = Function2(objMyMap); // write data to a binary file
objMyMap.ClearMemory(); // not real code in use, but for understanding the concept
bStatus = Function1(objMyMap); // re-allocate memory
ptrData = objMyMap.GetMapData();
//update the map data using ptrData variable
objMyMap.SetMapData(ptrData); // Do I need to set again or member pointer get updated automatically?
return true
}
int main()
{
ObjMapData objMyMap;
bool bStatus = Function3(objMyMap);
//default destructor of objMyMap can take care of the allocated memory cleanup
return 0;
}
Thank you for your time to confirm the dynamic memory allocation..
Although this may seem to be more to do with style than your question about memory leaks, I would handle the data privately within the class:
class ObjMapData
{
private:
int* itsMapData;
// consider adding 'datasize' member variable
........
public:
ObjMapData(){ itsMapData=NULL; }; // initialise member variable(s)!
~ObjMapData(){ delete[] itsMapData;}
ClearMemory() { delete[] itsMapData; itsMapData=NULL; }
.......
void CreateMapData(int size) { ClearMemory(); itsMapData= new int[size]; }
void FillDataFrom( ???? ) { ???? };
int* GetMapData() const { return itsMapData;}
}
You are then in a better position to improve the class by adding copy constructor and assignment methods which will prevent memory leaks when you use the class.
EDIT
You ask:
My concern here is which of the following is right: void
SetMapData(int* ptrData) Vs void SetMapData(int*&ptrData)
Both are 'right' in the sense that both allow the external (to the class) pointer to be copied and used within your class - with respect to 'memory leaks' it depends on which part of your code you want to manage the memory you allocated. You could:
Have a class handle allocation/deallocation internally
Allocate memory, use some class to manipulate it, deallocate memory outside class
Have a class allocate memory and later deallocate it outside the class
Allocate memory and have some class manipulate and deallocate it.
Usually I find 1 and 2 make more sense than 3 or 4. i.e. it is easier to follow what is going on, less likely to hide errors and so on.
However, as far as 'leaking memory' is concerned: it does not matter where the pointer to an allocated memory block is, how it has been copied, assigned or referenced - it is it's value as a memory address which is important. So, as long as you new and delete that memory address correctly you will not leak memory (whether those actions are inside a class or not).
If, in your application, you need to allocate/deallocate the int array external to your class, it does make some sense for the member functions reference the pointer as a hint to the reader that the class is not responsible for its deallocation - but some decent comments should make that clear anyway :)
Over the years I've come across umpteen bugs due to the mishandling of the "passing of ownership" of allocated memory (more so with good ol 'C') where some piece of code has been written assuming either that it has to free a block or someone else will do it.
Does that answer your question or have I missed the point?
I would like to know how delete works?
In main function I have deleted the cfact object. But still the cfact->Hello() works instead of throwing an error.
While debugging I found while delete happens, cfact releases the memory. as soon as factory* c2fact = newfun.Newfun("c2_fact"); line executes cfact gets some memory location.
class factory{
public:
virtual void Hello() = 0;
};
class c_fact: public factory
{
public:
void Hello(){
cout << "class c_fact: public factory"<<endl;
}
};
class c2_fact: public factory
{
public:
void Hello(){
cout << "class c2_fact: public factory"<<endl;
}
};
class callFun{
public:
virtual factory* Newfun(string data)
{
if(data == "c_fact")
{return new c_fact;}
else
{return new c2_fact;}
}
};
class newFun:public callFun{
public:
factory* Newfun(string data)
{
if(data == "c_fact")
{return new c_fact;}
else if (data == "c2_fact")
{return new c2_fact;}
}
};
int main()
{
newFun newfun;
factory* cfact = newfun.Newfun("c_fact");
delete cfact; //Deleted the instance
factory* c2fact = newfun.Newfun("c2_fact");
cfact->Hello();//Still it prints the output
c2fact->Hello();
system("pause");
return 0;
}
delete doesn't actually invalidate what it points to. It just tells the OS that the memory can be used for something else and that the program doesn't need it anymore.
If it not overwritten by other data your data will still be in memory and will still be accessible. This is a cause of many bugs that go undetected during development phase and later show up.
The fact that is is working now doesn't mean it will always work. For example if you move the code to another machine or if you restart your computer the code might segfault.
It is always a good practice to set pointers to NULL after delete. Or even better use smart pointers.
This is undefined behavior, most likely this works because the method Hello is not using any of the classes variables and thus is not using the this pointer. Trying outputting this in Hello and you should see an invalid pointer after the call to delete:
std::cout << std::hex << this << << std::endl ;
In my test case it comes back as 0 after delete
Dereferencing a deleted pointer is undefined behaviour. That means anything can happen, including the program appearing to "work". You cannot rely on any such behaviour.
When you delete the memory it is released. however, the content is usually not changed, so anything that is written in that memory is still there after the delete, but you don't know how long it will stay, as other functions can grab it and overwrite it with their own data.
On some compilers, when compiling in debug mode, the memory is marked, so that you can detect such errors as you did by reusing the deleted pointer. However that is not necessarily the default. So you should never reuse a pointer that was deleted.
Sorry I can't comment...
I compiled your code and you can observe that c2fact replaces the cfact you just destroyed (the output is
class c2_fact: public factory
class c2_fact: public factory
)
BTW if you put "cfact->Hello();" before you create your c2fact, the program may crash (which is what you seem to wish) because the mem blocks are not affected to any object. Note that this behavior may change depending on the memory monitoring and other running processes.