Suppose we have a class with a smart pointer. This class initializes a subsystem that the smart pointer relies on: similarly, this class closes the subsystem upon destruction.
If the smart pointer relies on said subsystem to free its memory, then if the destructor closes the subsystem first an issue arises.
class FontManager {
public:
FontManager() {
if(TTF_Init() < 0) {
printf( "SDL_ttf could not init! SDL_ttf Error: %s\n", TTF_GetError() );
return;
}
}
~FontManager() {
TTF_Quit();
}
std::unique_ptr<TTF_Font> font;
void operator()(TTF_Font* font) const { TTF_CloseFont(font); }
};
If I were using raw pointers the destructor would look like this.
~FontManager() {
// font is raw pointer
TTF_CloseFont(font);
TTF_Quit();
}
So, what gets called first, the pointer's destructor or the class' destructor?
Just as subobjects are constructed at the beginning of a class’s constructor (in the member initializer list, perhaps implicitly), they are destroyed at the end of the destructor (in the reverse order of their construction, as usual).
You can of course reset your pointers manually in your destructor; they will still be destroyed at the end of it, but with no effect. But the real answer is to encapsulate the subsystem (initialization) as its own resource, add an instance of that new class as an earlier member, and then let the containing class use the implicit destructor. This has the additional benefit of guaranteeing that the subsystem is initialized when you use it to allocate the smart pointer’s object.
Related
The code is pretty straight forward:
class SuperClass
{
public:
virtual void someMethod() = 0;
};
class SubClass : public SuperClass
{
public:
virtual void someMethod()
{
std::cout << "hello" << std::endl;
}
};
class CallerClass
{
public:
std::vector<SuperClass*> subClasses;
CallerClass()
{
subClasses.push_back(&SubClass());
}
void callMethods()
{
subClasses[0]->someMethod();
}
};
int main(int argx, char**argv)
{
CallerClass cc;
cc.callMethods();
return 0;
}
The problem occurs when I actually call try to call the subClass' 'someMethod()' in the CallerClass' 'callMethods()'. In Visual Studio, it simply breaks at that line of code without any explanation. I have solved the problem by changing push_back(&SubClass()) to push_back(new SubClass()).
I am curious as to why the latter works and not the former. I thought it was because an object created in a method will only exist within the method, and by using 'new', space was actually being allocated for that object after the function ended; but I added an int a = 1 to SuperClass and was able to access it using in a similar fashion to what's inside 'callMethods()'.
I must be missing some fundamental aspect of C++ here. Please inform me. Hopefully it's not something too obvious.
In
subClasses.push_back(&SubClass());
You are storing a pointer to a temporary object, which is destroyed just after.
Then, when you call someMethod, you are calling a method on an invalid object pointer which was already deleted.
With
subClasses.push_back(new SubClass());
You are storing a pointer to a valid object, so it works.
Yes, if you do push_back(&SubClass()) you are adding a pointer to the vector that points to a temporary object. At the end of the expression the temporary object will be deleted. When you call callMethods you are dereferencing a pointer to a deleted object. This is undefined behaviour, anything could happen, it could even work!
By calling push_back(new SubClass()); you are allocating an object on the heap and adding a pointer to that object to the vector. This object on the heap will not be deleted when the expression ends.
In fact this object will not be deleted at all and would be a memory leak in your program. CallerClass effectively owns the objects so it is its responsibility to delete them when it is done.
To fix the memory leak there are a couple of changes you need to make. You need to add a public virtual destructor to SuperClass:
virtual ~SuperClass(){};
This ensures that if you call the destructor on SuperClass the SubClass will also be destroyed properly. Then you need to ensure that delete is called in the CallerClass destructor. You could do that by explicitly writing a destructor, looping over the elements of the vector and calling delete but the easier, C++11 way, is to use smart pointers like std::unique_ptr. If you change your vector to:
std::vector<std::unique_ptr<SuperClass>> subClasses;
then the objects will be automatically deleted in the CallerClass destructor and you don't have to explicitly write a destructor at all.
Live Demo
Can anyone tell me what happens with object's memory if I forget to declare a destrucor in a C++ class? I mean, whether it is freed or causes memory leak?
An example or demo will be appreciated.
Thanks in advance.
It's often considered good practice to define a destructor for any non-trivial class (see the Rule of Three). However, in modern C++ (i.e. C++11 onwards), it's not as necessary as it used to be.
If your class is not inherited from anything else, any direct members (such as variables and objects) will be properly destroyed by the default destructor provided by the compiler. Similarly, if your object owns any heap-allocated objects which are wrapped in smart pointers, they will be destroyed safely too.
A problem arises if your object owns any heap-allocated data via raw pointers. The implicit destructor has no way of knowing what to do with them, so you will need a custom destructor to clear them up. For example:
class MyClass
{
int m_data1;
std::string m_data2;
std::shared_ptr<Widget> m_data3;
Widget *m_data4;
};
In the above example, members m_data1, m_data2, and m_data3 will all be cleared-up correctly without a custom destructor. However, the object pointed to by m_data4 will not be cleared up automatically. If it was allocated by MyClass, then it will usually result in a memory leak (unless it's getting freed by something else).
With all of that said, inheritance changes things in an important way. If your class is inherited by anything else then you should probably always give it a virtual destructor. If your object is deleted via a pointer to an inherited class, and that class does not have a virtual destructor, then the sub-class' destructor will never be called, potentially resulting in memory leaks.
For example:
class Parent
{
public:
Widget m_data1;
}
class Child : public Parent
{
public:
Widget m_data2;
}
int main()
{
Parent *ptr = new Child;
delete ptr; // <-- clears-up Parent but not Child
}
In the above example, ptr is of Parent type, so the delete only knows about the Parent part of the object. That means only m_data1 will be cleared-up correctly. Without a virtual destructor, it doesn't know about the Child part of the object, so m_data2 will not be cleared-up correctly (its destructor will never be called).
If destructor is not declared, compiler will generate destructor, that will call destructors of all members of object. Leak can be only if you are working with raw-memory (C files, memory allocation etc).
It depends on the class' data members. If the class manages resources, then it needs a destructor to release them (you should also provide a copy constructor and assignment operator, or make the class non-copyable and non-assignable).
If the class has built-in data members, or data members that manage their own resources, then the implicitly generated destructor is enough. It will call the destructor of all data members.
Lets say, for example, that I have a class that requires the use of some old C stuff (like pthreads or something), so for one reason or another, I've ended up with a malloc() call in my constructor, like so:
class Foo
{
public:
Foo()
{
someMutex = malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(someMutex);
someString = new string("yay string!");
}
private:
pthread_mutex_t * someMutex;
string * someString;
}
It seems like there is a lot of misinformation about destructors out there. I keep seeing examples of explicitly defined destructors calling delete on pointer based members, but I also keep reading that I don't need to explicitly define a destructor for a class to manage memory; all I need a destructor for are things like file handle cleanups and the like.
Thus leads to my question then: Even though someMutex was allocated with malloc and not the C++ new command, will the implicitly defined destructor still take care of it, or do I have to do it?
Also, lets just settle another question of mine, since its so closely related. In the class above, do I need to explicitly define a destructor in order to call delete on someString, or is that taken care of for me?
Not only do you need to define a destructor to do the cleanup, you also need to declare (and optionally define) a copy constructor and copy assignment operator for your class, to ensure that copies are made correctly.
The implicitly-defined destructor destroys member variables. So, for example, if you had a member variable of type string, the destructor will destroy that variable all on its own. However, the destructor for a pointer (like string*) is a no-op: you are responsible for destroying the pointed-to object.
You also need to define the copy operations for this class, or at least suppress generation of the default copy operations that the compiler provides for you. Why? Because by default, the copy operations just copy each member variable. So, if for example you were to write:
{
Foo x;
Foo y(x);
} // Uh oh
Both x and y are destroyed at the end of the block. At this point, both x and y point to the same dynamically allocated mutex and string, so the mutex and string would be destroyed twice (once for x and once for y).
The better option is not to use manual memory allocation at all. Rather, you should make someString a direct member of the class (i.e., declare it string someString;) or you should use a smart pointer of some kind to manage its lifetime (like unique_ptr or shared_ptr). Similarly, you should use a smart pointer with a custom deleter to manage the lifetime of the mutex, unless your class is noncopyable, in which case you can make the mutex a direct member of the class.
Yes, you have to define a destructor and destroy your objects (someMutex and someString).
But, as you have allocated someMutex with malloc, you must free it with free.
Take care for not to mix them.
Remember:
allocated with malloc, freed with free
allocated with new, freed with delete
allocated with new[], freed with delete[]
Instead of storing a pointer to a string in your class, I'd just store an instance of string as a data member (using "stack semantics").
Moreover, instead of storing a pointer to a "raw" pthread_mutex_t, I'd define a C++ class to wrap this pthread_mutex_t resource using RAII (creating the pthread_mutex_t in its constructor, and destroying it in its destructor), and then I'd store an instance of this C++ class as a data member of Foo.
//
// C++ RAII wrapper on raw C pthread_mutex_t resource.
//
class PThreadMutex
{
public:
// Creates a pthread_mutex_t.
PThreadMutex()
{
pthread_mutex_init(&m_mutex, ...);
// Check for errors, and throw exceptions on errors
}
// Destroys a pthread_mutex_t
~PThreadMutex()
{
pthread_mutex_destroy(&m_mutex);
}
// Other member functions
// ...
// May define move constructor and move assignment operator for C++11
// ...
private:
pthread_mutex_t m_mutex;
};
class Foo
{
public:
Foo()
: m_someString("yay string!")
// m_someMutex initialized by its default constructor
{
}
~Foo()
{
// Nothing to do: C++ compiler will call the destructors
// of class data members, releasing their associated resources.
}
private:
//
// Class "building blocks":
//
PThreadMutex m_someMutex;
string m_someString;
};
In this way, the compiler-generated destructor for Foo will automatically call each data members destructors, releasing their resources.
In general, each "raw" C resource (pthread_mutex_t, FILE *, etc.) should be wrapped in a C++ class using RAII, and instances of these classes (like they were kind of "building blocks") should be used as data members of other classes.
This helps simplify your code (and writing exception-safe code as well); if you use this pattern you can achieve a good level of code safety and composability.
No, destructor shouldn't delete those data (it may be pointer to memory allocated somewhere else in your application). So you have to write your own destructor.
And one more thing. Once you allocate memory with malloc you should free it with free().
Whether you need to define a destructor or not depends of if the current object OWNS the created objects or it just create them for some other object to manage, respectivelly.
When you allocate heap memory with malloc() you should free it with free().
When you create objects with new, then you must delete it with delete.
When you create an array with new[], then you must delete it with delete[].
Implicit destructors destroy member variables but in your case they are pointers so memory allocated for the pointers thenselves will be recovered, but not the allocated memory you just malloc'ed.
Another option is using a "smart pointer" (http://en.wikipedia.org/wiki/Smart_pointer), which will actually delete the pointed object when the current object is deleted (or get out of scope).
How does C++ ensure that destructors are called for stack assigned objects? What happens to the destructor function (or a pointer to it) when I assign dynamic memory as follows:
class MyClass {
public:
~MyClass()
{
std::cout<<"Destructor called."<<std::endl;
}
MyClass()
{
std::cout<<"Constructor called."<<std::endl;
}
};
....................................................................
//Limit scope for example
{
MyClass instance;
}
The constructor and destructor are both called. What's going on here?
The compiler inserts a call to the destructor for the object at an appropriate position.
You wouldn't wonder why this
{
int i;
}
creates and destroys i automatically, would you? C++ does a lot to allow you to create types that behave just like built-in types. And just like with built-in types, in C++ (other than in, say, Java or C#), this
{
MyClass instance;
}
doesn't just define a reference that might be bound to null or some actual object. It creates an actual object.
Object creation comes in two steps: First (upon entering the scope) the raw memory is provided. Then (when the object definition is encountered) the constructor is called. For built-in types no constructor is called. If you don't initialize a built-in variable, it has a random value. (Actually it's whatever the bit pattern was at the memory provided in step #1.) Object deletion, too, comes in two steps: First, the destructor is called (again, not for built-ins), then the memory is returned to the run-time system.
(Note that providing and deleting memory for stack variables usually is as cheap as incementing/decrementing a register.)
The constructor is called as soon as the variable is created. As for the destructor, the compiler emits code at the end of scope to call the destructor. To get a feel for this, try using a 'goto', or switch/case construct to prematurely exit the scope, and watch the compiler complain.
Yes, both the constructor and destructor are called. And even more important:
{
MyClass instance;
throw "exception";
}
in this example, the destructor is also called. That is why I always prefer to allocate my objects on stack (or at least wrap the dynamic allocations with a stack-allocated guardians).
The constructor is called because you're creating an object. The destructor is called because your cleaning up that object. Remember, in C++, objects declared on the stack are automatically cleaned up when their containing scope goes away.
Well, it did not call the destructor just after constructor.
It calls it when it about to terminate the programme.
int main() {
MyClass obj;
cout<<"testing....1"<<endl;
cout<<"testing....2"<<endl;
return 0;
}
ans:
Constructor called.
testing....1
testing....2
Destructor called.
I really can't believe I couldn't find a clear answer to this...
How do you free the memory allocated after a C++ class constructor throws an exception, in the case where it's initialised using the new operator. E.g.:
class Blah
{
public:
Blah()
{
throw "oops";
}
};
void main()
{
Blah* b = NULL;
try
{
b = new Blah();
}
catch (...)
{
// What now?
}
}
When I tried this out, b is NULL in the catch block (which makes sense).
When debugging, I noticed that the conrol enters the memory allocation routine BEFORE it hits the constructor.
This on the MSDN website seems to confirm this:
When new is used to allocate memory
for a C++ class object, the object's
constructor is called after the memory
is allocated.
So, bearing in mind that the local variable b is never assigned (i.e. is NULL in the catch block) how do you delete the allocated memory?
It would also be nice to get a cross platform answer on this. i.e., what does the C++ spec say?
CLARIFICATION: I'm not talking about the case where the class has allocated memory itself in the c'tor and then throws. I appreciate that in those cases the d'tor won't be called. I'm talking about the memory used to allocate THE object (Blah in my case).
You should refer to the similar questions here and here.
Basically if the constructor throws an exception you're safe that the memory of the object itself is freed again. Although, if other memory has been claimed during the constructor, you're on your own to have it freed before leaving the constructor with the exception.
For your question WHO deletes the memory the answer is the code behind the new-operator (which is generated by the compiler). If it recognizes an exception leaving the constructor it has to call all the destructors of the classes members (as those have already been constructed successfully prior calling the constructor code) and free their memory (could be done recursively together with destructor-calling, most probably by calling a proper delete on them) as well as free the memory allocated for this class itself. Then it has to rethrow the catched exception from the constructor to the caller of new.
Of course there may be more work which has to be done but I cannot pull out all the details from my head because they are up to each compiler's implementation.
If an object cannot complete destruction because the constructor throws an exception, the first thing to happen (this happens as part of the constructor's special handling) is that all member variables to have been constructed are destroyed - if an exception is thrown in the initializer list, this means that only elements for which the initializer has completed are destroyed.
Then, if the object was being allocated with new, the appropriate deallocation function (operator delete) is called with the same additional arguments that were passed to operator new. For instance, new (std::nothrow) SomethingThatThrows() will allocate memory with operator new (size_of_ob, nothrow), attempt to construct SomethingThatThrows, destroy any members that were successfully constructed, then call operator delete (ptr_to_obj, nothrow) when an exception is propagated - it won't leak memory.
What you have to be careful is allocating several objects in succession - if one of the later ones throws, the previous ones will not be automatically be deallocated. The best way around this is with smart pointers, because as local objects their destructors will be called during stack unwinding, and their destructors will properly deallocate memory.
If the Constructor throws the memory allocated for the object is auto-magically returned to the system.
Note the destructor of the class that threw will not be called.
But the destructor of any base class (where the base constructor has completed) will also be called.
Note:
As most other people have noted members may need some clean up.
Members that have been fully initialized will have their destructors called, but if you have any RAW pointer members that you own (ie delete in the destructor) you will have to do some clean up before you do the throw (another reason not to use owned RAW pointers in your class).
#include <iostream>
class Base
{
public:
Base() {std::cout << "Create Base\n";}
~Base() {std::cout << "Destroy Base\n";}
};
class Deriv: public Base
{
public:
Deriv(int x) {std::cout << "Create Deriv\n";if (x > 0) throw int(x);}
~Deriv() {std::cout << "Destroy Deriv\n";}
};
int main()
{
try
{
{
Deriv d0(0); // All constructors/Destructors called.
}
{
Deriv d1(1); // Base constructor and destructor called.
// Derived constructor called (not destructor)
}
}
catch(...)
{
throw;
// Also note here.
// If an exception escapes main it is implementation defined
// whether the stack is unwound. By catching in main() you force
// the stack to unwind to this point. If you can't handle re-throw
// so the system exception handling can provide the appropriate
// error handling (such as user messages).
}
}
From the C++ 2003 Standard 5.3.4/17 - New:
If any part of the object initialization described above terminates by throwing an exception and a suitable deallocation function can be found, the deallocation function is called to free the memory in which the object was being constructed, after which the exception continues to propagate in the context of the new-expression. If no unambiguous matching deallocation function can be found, propagating the exception does not cause the object’s memory to be freed. [Note: This is appropriate when the called allocation function does not allocate memory; otherwise, it is likely to result in a memory leak. ]
So there may or may not be a leak - it depends on whether an appropriate deallocator can be found (which is normally the case, unless operator new/delete have been overridden).In the case where there's a suitable deallocator, the compiler is responsible for wiring in a call to it if the constructor throws.
Note that this is more or less unrelated to what happens to resources acquired in the constructor, which is what my first attempt at an answer discussed - and is a question that is discussed in many FAQs, articles, and postings.
The long and short of it is that if you haven't made any allocations of other entities in you object(as in your example) then the memory that was allocated will be deleted automatically. However, any new statements(or anything else that directly manages memory) needs to be handled in a catch statement in the constructor, Otherwise the object is deleted without deleting it's subsequent allocations and you, my friend, have a leak.
Quoted from C++ FAQ (parashift.com):
[17.4] How should I handle resources if my constructors may throw
exceptions?
Every data member inside your object should clean up its own mess.
If a constructor throws an exception, the object's destructor is not
run. If your object has already done something that needs to be undone
(such as allocating some memory, opening a file, or locking a
semaphore), this "stuff that needs to be undone" must be remembered
by a data member inside the object.
For example, rather than allocating memory into a raw Fred* data
member, put the allocated memory into a "smart pointer" member object,
and the destructor of this smart pointer will delete the Fred
object when the smart pointer dies. The template std::auto_ptr is an
example of such as "smart pointer." You can also write your own
reference counting smart pointer. You can also use smart pointers
to "point" to disk records or objects on other machines.
By the way, if you think your Fred class is going to be allocated
into a smart pointer, be nice to your users and create a typedef
within your Fred class:
#include <memory>
class Fred {
public:
typedef std::auto_ptr<Fred> Ptr;
...
};
That typedef simplifies the syntax of all the code that uses your
objects: your users can say Fred::Ptr instead of
std::auto_ptr<Fred>:
#include "Fred.h"
void f(std::auto_ptr<Fred> p); // explicit but verbose
void f(Fred::Ptr p); // simpler
void g()
{
std::auto_ptr<Fred> p1( new Fred() ); // explicit but verbose
Fred::Ptr p2( new Fred() ); // simpler
...
}
The problem described is as old as the road to Rome, to use a Dutch saying. I have worked out the problem and a memory allocation for an object that might throw an exception looks as follows:
try
{
std::string *l_string =
(_heap_cleanup_tpl<std::string>(&l_string),
new std::string(0xf0000000, ' '));
delete l_string;
}
catch(std::exception &)
{
}
Before the actual call to the new-operator, a nameless (temporary) object is created, which receives the address of the allocated memory through a user-defined new-operator (see the rest of this answer). In case of normal programme execution, the temporary object passes the result of the new-operator (the newly created and fully constructed object, in our case a very very very long string) to the variable l_string. In case of an exception, the value is not passed on, but the destructor of the temporary object deletes the memory (without ofcourse calling the destructor of the main object).
It is a bit fuzzy way of dealing with the issue, but it works. Problems may arise because this solution requires a user-defined new-operator and a user-defined delete-operator to go allong with it. The user-defined new/delete-operators would have to call the C++-standard library's implementation of new/delete-operators, but I have left that out for briefity and relied on malloc() and free() instead.
It is not the final answer, but I think it is worth working this one out.
PS: There was an 'undocumented' feature in the code below, so I have made an improvement.
The code for the temporary object is as follows:
class _heap_cleanup_helper
{
public:
_heap_cleanup_helper(void **p_heap_block) :
m_heap_block(p_heap_block),
m_previous(m_last),
m_guard_block(NULL)
{
*m_heap_block = NULL;
m_last = this;
}
~_heap_cleanup_helper()
{
if (*m_heap_block == NULL) operator delete(m_guard_block);
m_last = m_previous;
}
void **m_heap_block, *m_guard_block;
_heap_cleanup_helper *m_previous;
static _heap_cleanup_helper *m_last;
};
_heap_cleanup_helper *_heap_cleanup_helper::m_last;
template <typename p_alloc_type>
class _heap_cleanup_tpl : public _heap_cleanup_helper
{
public:
_heap_cleanup_tpl(p_alloc_type **p_heap_block) :
_heap_cleanup_helper((void **)p_heap_block)
{
}
};
The user-defined new-operator is as follows:
void *operator new (size_t p_cbytes)
{
void *l_retval = malloc(p_cbytes);
if (
l_retval != NULL &&
*_heap_cleanup_helper::m_last->m_heap_block == NULL &&
_heap_cleanup_helper::m_last->m_guard_block == NULL
)
{
_heap_cleanup_helper::m_last->m_guard_block = l_retval;
}
if (p_cbytes != 0 && l_retval == NULL) throw std::bad_alloc();
return l_retval;
}
void operator delete(void *p_buffer)
{
if (p_buffer != NULL) free(p_buffer);
}
I think it's kind of wierd for a constructor to raise an exception.
Could you have a return value and test it in your main?
class Blah
{
public:
Blah()
{
if Error
{
this.Error = "oops";
}
}
};
void main()
{
Blah* b = NULL;
b = new Blah();
if (b.Error == "oops")
{
delete (b);
b = NULL;
}