I've just started combining my knowledge of C++ classes and dynamic arrays. I was given the advice that "any time I use the new operator" I should delete. I also know how destructors work, so I think this code is correct:
main.cpp
...
int main()
{
PicLib *lib = new PicLib;
beginStorage(lib);
return 0;
}
void beginStorage(PicLib *lib)
{
...
if (command != 'q')
{
//let's assume I add a whole bunch
//of stuff to PicLib and have some fun here
beginStorage(lib);
}
else
{
delete lib;
lib = NULL;
cout << "Ciao" << endl;
}
}
PicLib.cpp
...
PicLib::PicLib()
{
database = new Pic[MAX_DATABASE];
num_pics = 0;
}
PicLib::~PicLib()
{
delete[] database;
database = NULL;
num_pics = 0;
}
...
I fill my PicLib with a Pic class, containing more dynamic arrays. Pic's destructor deletes them in the same manner seen above. I think that delete [] database gets rid of all those classes properly.
So is the delete in main.cpp necessary? Everything looking hunky dory here?
There are a couple of problems:
int main()
{
PicLib *lib = new PicLib;
beginStorage(lib);
return 0;
}
It is best to allocate and delete memory in the same scope so that it is easy to spot.
But in this case just declare it locally (and pass by reference):
int main()
{
PicLib lib;
beginStorage(lib);
return 0;
}
In beginStorage()
But I see no reason to manipulate a pointer. Pass it by reference and just use it locally.
void beginStorage(PicLib& lib)
{
....
}
In the PicLib class you have a RAW pointer: databases.
If you have a RAW pointer that you own (you create and destroy it) then you must override the compiler generated versions of the copy constructor and assignment operator. But in this case I see no reason touse a pointer it would be easier to just use a vector:
class PivLib
{
private:
std::vector<Pic> databases;
};
Yes, anything you create with new must be deleted with delete, and anything created with new[] must be deleted with delete[], at some point.
There are some things I'd point out in your code though:
Prefer std::vector<> over using new[] and delete[]. It'll do the memory management for you. Also have a look at smart pointers like auto_ptr, shared_ptr and in C++0x unique_ptr for automatic memory management. These help save you from forgetting a delete and causing a memory leak. If you can, don't use new/new[]/delete/delete[] at all!
If you have to new and delete something, it's a very good idea to new in a class constructor, and delete in a class destructor. When exceptions are thrown, objects go out of scope etc., their destructors are called automatically, so this helps prevent memory leaks. It's called RAII.
Having beginStorage delete its parameter is potentially a bad idea. It could crash if you call the function with a pointer not created with new, because you can't delete any pointer. It'd be better if main() created a PicLib on the stack rather than using new and delete, and for beginStorage to take a reference and not delete anything.
Yes it is necessary, unless you use an auto_ptr (and read up on the semantics of auto_ptr before you use it -- you can't copy it arround).
for example :
int main()
{
auto_ptr<PicLib> lib = new PicLib;
beginStorage(lib);
return 0;
} // auto_ptr goes out of scope and cleans up for you
else doesn't go with while. You'd want something more like:
void beginStorage(PicLib *lib)
{
while (command != 'q')
{
//let's assume I add a whole bunch
//of stuff to PicLib and have some fun here
}
delete lib;
lib = NULL; // Setting to NULL is not necessary in this case,
// you're changing a local variable that is about
// to go out of scope.
cout << "Ciao" << endl;
}
The delete looks good, but you should make sure to document that beginStorage takes ownership of the PicLib object. That way anyone using beginStorage knows that they don't have to delete it later.
The delete in main.cpp is necessary.
This is probably a matter of personal preference, but I would advise against calling new and delete in separate logical parts (here the delete call on the PicLib instance is in a separate function). Usually it's better to have the responsibility for allocation and deallocation given to just one part.
#AshleysBrain has a better suggestion (about creating PicLib the stack), although this might cause problems if PicLib takes up too much memory.
Generally you want to delete in the same place as you new. It makes the accounting easier. Better is to use a smart pointer (scoped_ptr in this case), which means that your code is still correct even if the body of the while throws an exception and terminates prematurely.
Everything looks good.
The delete in main.cpp is necessary because if you didn't call delete then the destructor is not run and your array is not deleted. You'd also be leaking the memory for the class, not just the array.
Yes, otherwise the destructor for PicLib will not be called.
One stylistic note though: If you new a method-scope object in a function, try and delete it in the same function. As a junior engineer that has had to go through large projects fixing other people's memory leaks...this makes things a lot easier for other people to read. From the looks of it, you could delete *lib after beginStorage() returns. Then it would be easier to see the scope of *lib in one place.
Related
I use extra brackets in my code. I thought when the destructor should be called after the local variable scope is ended but it doesn't work like this:
class TestClass {
public:
TestClass() {
printf( "TestClass()\n" );
}
~TestClass() {
printf( "~TestClass()\n" );
}
};
int main() {
int a, b, c;
{
TestClass *test = new TestClass();
}
}
It outputs:
TestClass()
So it doesn't call the destructor of the TestClass but why? If I call it manually (delete test) it calls the destructor, right. But why it doesn't call the destructor in the first case?
TestClass *test = new TestClass();
You using new which creates a dynamically allocated object (most likely placed on the heap). This type of resource needs to be manually managed by you. By managing, you should use delete on it after you have done using it.
{
TestClass *test = new TestClass();
// do something
delete test;
}
But for the most of your purposes and intents, you just have to use automatic-storage objects, which frees you the hassle of having to manually manage the object. It would also most likely to have better performance especially in short-lived objects. You should always prefer to use them unless you have a really good reason not to do so.
{
TestClass test;
// do something
}
However, if you need the semantics of dynamically allocated objects or that of pointers, it will always be better to use some mechanism to encapsulate the deletion/freeing of the object/resource for you, which also provides you additional safety especially when you are using exceptions and conditional branches. In your case, it would be better if you use std::unique_ptr.
{
std::unique_ptr<TestClass> test(new TestClass());
// auto test = std::make_unique<TestClass>(); in C++14
// do something (maybe you want to pass ownership of the pointer)
}
The following is a relevant link to help you decide whether to use automatic storage objects or dynamically allocated objects: Why should C++ programmers minimize use of 'new'?
Because you have a pointer to a dynamically allocated object. Only the pointer goes out of scope, not the object it points to. You have to call delete on the pointer in order for the pointee's destructor to get called.
Try with an automatic storage object instead:
{
TestClass test;
}
Here, the destructor will be called on exiting the scope.
The use of raw pointers to dynamically allocated objects in C++ is discouraged because it can easily lead to resource leaks like the one shown in your code example. If pointers to dynamically allocated objects are really needed, it is wise to handle them with a smart pointer, rather than to attempt to manually deal with their destruction.
This answer is good enough but just to add some more.
I see you have been coded with Java. In C++ to create variable/object in stack keyword new is not needed. Actually when you use keyword new your object is creating in heap and it doesn't destroys after leaving scope. To destroy it you need to call delete in your case delete test;
In such a structure as yours, after leaving scope you just lose pointer what points into object, so after leaving scope you cannot free memory and call destructor, but eventually OS call destructor just after exit() instruction is executed.
To sum up C++ != Java
always delete pointer even if it is just in function call stack?
Isn't it disappeared when function stack released?
// just Simple class
class CSimple{
int a;
}
// just simple function having pointer.
void simpleFunc(){
CSimple* cSimple = new CSimple();
cSimple->a = 10;
//.. do sth
delete cSimple; // <<< Always, do I have to delete 'cSimple' to prevent the leak of memory?
}
void main(){
for( int =0 ; i< 10 ; i++){
simpleFunc();
}
}
when function stack released?
It is true that "CSimple *csimple" goes away when the function returns.
However, there's a big difference between the pointer, and what it's pointed to.
When a pointer object gets destroyed, nothing happens to whatever the pointer is pointing to. There isn't just one, but two objects here:
The pointer.
What it's pointing to.
In this case, the pointer is pointing to an object in dynamic scope that was created with new.
Nothing is going to happen to this object, otherwise, so you will leak memory.
Therefore, this object needs to be deleted.
After you understand, and fully wrap your brain around this concept, your next step will be to open your C++ book to the chapter that talks about the std::unique_ptr and std::shared_ptr classes, which will take care of these pesky details, for you. You should learn how to use them. Modern C++ code rarely needs to delete something; rather these smart pointers do all the work.
Yes.
On scope exit (ex. when function exists or block { ... } finishes), all objects created on stack will be destroyed and memory will be freed.
This applies to your case, ie. the pointer will be destroyed and memory occupied by the pointer will be freed. The object pointed by the pointer will not be cleared.
This is a common problem and a nightmare when you deal with multiple flow paths (if-else ladders, many return statements) and exceptions.
To solve this problem, we employ 2 main strategies:
RAII
Smart pointers (std::unique_ptr, boost::scoped_ptr, legacy std::auto_ptr, etc).
RAII - without academic consideration - is just creating object on stack, like this:
{
std::string s;
fancy_object obj;
}
When we exit he scope, obj and s destructors will be called duing stack unwinding. Compiler ensures this for all flow paths and will keep proper order of deallocations for us.
If you need to allocate memory on heap, using new, use a smart pointer.
int foo()
{
std::unique_ptr<Object> o(new Object);
... some more code ...
if( something ) { return -1 }
... some more code ...
if( something_else ) { return -2 }
else { not yet }
return 0;
}
As you can see, we can leave the scope using 3 "exists". Normally, you'd need to clear your memory in all cases, which is prone to human errors.
Instead of clearing the object manually in all 3 palces, we rely on automatic destructor call for objects created on stack. Compiler will figure it out. When we leave the scope, std::unique_ptr destructor will be called, calling delete on Object.
Don't be affraid of smart poiners. They are not "slow", "bloat" or other nonsense. Smart poiners are designed to have no overhead on access, adding extra security.
Very similar technique is used for locks. Check out std::lock_guard class.
Yes, you must delete the data that is being pointed to.
The pointer itself is on the stack and does not need to be deleten.
You can, however, store cSimple on the stack, then you don't have to delete it:
void simpleFunc(){
CSimple cSimple; // no new
cSimple.a = 10; // "." instead of "->"
//.. do sth
// no deletion
}
According to the following article: Why isn’t the destructor called at the end of scope?
Code that creates an object using new and then deletes it at the end of the same scope is ugly, error-prone, inefficient, and usually not exception-safe. For example:
void very_bad_func() // ugly, error-prone, and inefficient
{
X* p = new X;
// use p
delete p; // not exception-safe
}
My Code which I hope is not ugly:
I am creating an object of type TiXmlDocumentand the delete it by the end of the function.
void DataLoader::readXmlFile(const string & file)
{
TiXmlDocument *doc = new TiXmlDocument(file.c_str());
bool loadOkay = doc->LoadFile();
TiXmlHandle hdl(doc);
//work is done in here
if(loadOkay)
{
TiXmlElement * pRoot = hdl.FirstChildElement().Element();//.FirstChildElement().Element();
parseFile(pRoot);
}
else
{
cout <<"Error: "<< doc->ErrorDesc()<<endl;
}
//deallocate doc
delete doc;
}
Question(s):
Should I use DataLoader::~DataLoader() {} destructor in order to insure that the object is deleted after I leave the scope of the function? without the need of explicitly deleting it delete doc.
As suggested I did the following:
TiXmlDocument doc(xmlFile.c_str());
bool loadOkay = doc.LoadFile();
TiXmlHandle hdl(&doc);
I am starting to think that using dynamic memory just like java and c# is not a good practice (should be used in a responsible way) in c++. If there is no real cause to use it then don't. If not handled correctly it will cause a memory leak which is hard to trace.
Either create your object without new:
void func()
{
X p;
// use p
}
Or if you must use new (for example, it's a big object) then use a smart pointer:
void func()
{
std::unique_ptr<X> p(new X);
// use p
}
Problem solved!
That's still ugly (in my view), and certainly error-prone, inefficient, and not exception-safe. If an exception is thrown during this function, the delete won't happen, and you'll leak memory.
In this case, there's no need for new at all; use an automatic variable, which will be destroyed automatically when the function exits, whether by reaching the end, returning, or throwing.
TiXmlDocument doc(file.c_str());
If you did need dynamic allocation for some reason, then use a smart pointer or other RAII type to get the same automatic behaviour:
auto doc = std::make_unique<TiXmlDocument>(file.c_str()); // C++14 or later
std::unique_ptr<TiXmlDocument> doc(new TiXmlDocument(file.c_str())); // C++11
To answer the last question: use the destructor to deallocate resources managed by the class instance, not transient resources used within a function call. Again, you should usually use RAII types as member variables to manage these resources automatically, so that you don't need to write a destructor yourself.
I have the following code and I get stack overflow error can anyone please explain me What's wrong here. from my understanding this pointer points to current object so why I cant delete it in a destructor;
class Object
{
private:
static int objCount;
public:
int getCount()
{
int i =10;
return i++;
}
Object()
{
cout<< "Obj Created = "<<++objCount<<endl;
cout <<endl<<this->getCount()<<endl;
}
~Object()
{
cout<<"Destructor Called\n"<<"Deleted Obj="<<objCount--<<endl;
delete this;
}
};
int Object::objCount = 0;
int _tmain(int argc, _TCHAR* argv[])
{
{
Object obj1;
}
{
Object *obj2 = new Object();
}
getchar();
return 0;
}
You're doing delete this; in your class's destructor.
Well, delete calls the class's destructor.
You're doing delete this; in your class's destructor.
...
<!<!<!Stack Overflow!>!>!>
(Sorry guys I feel obliged to include this... this might probably spoil it sorrrryyyy!
Moral of the boring story, don't do delete this; on your destructor (or don't do it at all!)
Do [1]
Object *obj = new Object();
delete obj;
or much better, just
Object obj;
[1]#kfsone's answer more accurately points out that the stack overflow was actually triggered by obj1's destructor.
'delete this' never makes sense. Either you're causing an infinite recursion, as here, or you're deleting an object while it is still in use by somebody else. Just remove it. The object is already being deleted: that's why you're in the destructor.
The crash you are having is because of the following statement:
{
Object obj1;
}
This allocates an instance of "Object" on the stack. The scope you created it in ends, so the object goes out of scope, so the destructor (Object::~Object) is invoked.
{
Object obj1;
// automatic
obj1.~Object();
}
This means that the next instruction the application will encounter is
delete this;
There are two problems right here:
delete calls the object's destructor, so your destructor indirectly calls your destructor which indirectly calls your destructor which ...
After the destructor call, delete attempts to return the object's memory to the place where new obtains it from.
By contrast
{
Object *obj2 = new Object();
}
This creates a stack variable, obj2 which is a pointer. It allocates memory on the heap to store an instance of Object, calls it's default constructor, and stores the address of the new instance in obj2.
Then obj2 goes out of scope and nothing happens. The Object is not released, nor is it's destructor called: C++ does not have automatic garbage collection and does not do anything special when a pointer goes out of scope - it certainly doesn't release the memory.
This is a memory leak.
Rule of thumb: delete calls should be matched with new calls, delete [] with new []. In particular, try to keep new and delete in matching zones of authority. The following is an example of mismatched ownership/authority/responsibility:
auto* x = xFactory();
delete x;
Likewise
auto* y = new Object;
y->makeItStop();
Instead you should prefer
// If you require a function call to allocate it, match a function to release it.
auto* x = xFactory();
xTerminate(x); // ok, I just chose the name for humor value, Dr Who fan.
// If you have to allocate it yourself, you should be responsible for releasing it.
auto* y = new Object;
delete y;
C++ has container classes that will manage object lifetime of pointers for you, see std::shared_ptr, std::unique_ptr.
There are two issues here:
You are using delete, which is generally a code smell
You are using delete this, which has several issues
Guideline: You should not use new and delete.
Rationale:
using delete explicitly instead of relying on smart pointers (and automatic cleanup in general) is brittle, not only is the ownership of a raw pointer unclear (are you sure you should be deleting it ?) but it is also unclear whether you actually call delete on every single codepath that needs it, especially in the presence of exceptions => do your sanity (and that of your fellows) a favor, don't use it.
using new is also error-prone. First of all, are you sure you need to allocate memory on the heap ? C++ allows to allocate on the stack and the C++ Standard Library has containers (vector, map, ...) so the actual instances where dynamic allocation is necessary are few and far between. Furthermore, as mentioned, if you ever reach for dynamic allocation you should be using smart pointers; in order to avoid subtle order of execution issues it is recommend you use factory functions: make_shared and make_unique (1) to build said smart pointers.
(1) make_unique is not available in C++11, only in C++14, it can trivially be implemented though (using new, of course :p)
Guideline: You shall not use delete this.
Rationale:
Using delete this means, quite literally, sawing off the branch you are sitting on.
The argument to delete should always be a dynamically allocated pointer; therefore should you inadvertently allocate an instance of the object on the stack you are most likely to crash the program.
The execution of the method continues past this statement, for example destructors of local objects will be executed. This is like walking on the ghost of the object, don't look down!
Should a method containing this statement throw an exception or report an error, it is difficult to appraise whether the object was successfully destroyed or not; and trying again is not an option.
I have seen several example of usage, but none that could not have used a traditional alternative instead.
Alright so Say I have a class with all its definition, bla bla bla...
template <class DT>
class Foo{
private:
DT* _data;
//other stuff;
public:
Foo(DT* data){ _data = data; }
virtual ~Foo(){ delete _data; }
//other methods
};
And then I have in the main method:
int main(){
int number = 12;
Foo<anyRandomClass>* noPrimitiveDataObject = new Foo<anyRandomClass>(new anyRandomClass());
Foo<int>* intObject = new Foo<int>(number);
delete noPrimitiveDataObject; //Everything goes just fine.
delete intObject; //It messes up here, I think because primitive data types such as int are allocated in a different way.
return 0;
}
My question is: What could I do to have both delete statements in the main method work just fine?
P.S.: Although I have not actually compiled/tested this specific code, I have reviewed it extensively (as well as indented), so if you find a mistake, please be nice.
You're taking the address of a literal and then calling delete on it later, which is wrong. It was not allocated with new, therefore you cannot deallocate it with delete (nor would it make any sense to).
If you had written new int(12) instead it would be ok, however, there are other problems.
First, your class violates The Rule of Three. What happens if I copy intObject and then call delete on both of them? You end up calling delete on the same pointer twice.
Second, why are you allocating these things dynamically to begin with? You create an RAII style wrapper to handle deallocation for you... and then proceed to allocate it manually. What problem is that solving?
I suppose this is an exercise for you, and that's great. Just remember what problem you're trying to solve with this code.
If I am using a std::vector<T> I am certainly not going to use it like this:
std::vector<int> *v = new std::vector<int>;
It defeats the entire purpose of using a vector! Now I have to manually manage this pointer/memory, and that's the problem that the vector class (and other RAII style classes) were created to solve.
So, to use it properly, you do this:
void foo()
{
std::vector<int> v;
// do stuff with v
// it allocates its memory dynamically so you don't have to.
// when we exit the function the destructor is called, the memory
// deallocated, and life continues as it should.
}
Use automatic storage duration to your advantage, that's the whole point. Also be very clear about who owns the memory. If it is not clear from your class design who owns a given chunk of memory then it is not safe to delete it in your destructor.
Ok, you changed the code to this now:
int number = 12;
// ...
Foo<int>* intObject = new Foo<int>(number);
Same problem; you are taking the address of a variable allocated with automatic storage duration and then calling delete on it. This is wrong. Anything you allocate with new you deallocate with delete, but nothing else. Ever. That's it.
It seem like you didn't know you can do new int(12). So for example you could change your code to the following:
Foo<int>* intObject = new Foo<int>(new int(12));
(I'm assuming this is just for learning, as not using new altogether would be better).
Also, I just noticed your code is wrong, perhaps you wanted the following:
Foo(DT* data){ _data = data; }
virtual ~Foo(){ delete _data; }
Side Note
Before posting a question, at least try to compile your examples.