Suppose I have a pointer to a dynamically allocated array of 10 elements:
T* p = new T[10];
Later, I want to release that array:
delete[] p;
What happens if one of the T
destructors throws an exception? Do the other elements still get destructed? Will the memory be released? Will the exception be propagated, or will program execution be terminated?
Similarly, what happens when a std::vector<T>
is destroyed and one of the T
destructors throws?
I can not see it explicitly called out in the standard:
Just that they will be called in reverse order of creation
5.3.5 Delete [expr.delete]
And that the memory deallocation will be done even if the exception is thrown:
I tried the following code in G++ and it shows that that no more destructors get called after the exception:
Execute:
Which all leads back to this (very old answer):
throwing exceptions out of a destructor
Couldn't find anything about destructors except for
I guess that after throwing no more destructors are called, but I'm not sure.
To answer your second question, if you used std::vector instead, there wouldn't be any need for a call to delete, you're not using pointers (the vector class is internally I believe, but this is not up to you to manage).
Okay, here is some experimental code:
Running the code gave the following output on g++ 4.6.0:
So it would seem that
std::terminate
is called immediately as soon as the first destructor throws. The other elements are not destructed, and the memory is not released. Can anyone confirm this?Never do that. If there is already an active exception,
std::terminate
will be called: "Bang, you're dead". Your destructor must. Not. Throw. Resist.edit: Relevant section from the Standard (14882 2003), 15.2 Constructors and Destructors
[except.dtor]
:Testcase for playing around (in real life, throw something that is derived from
std::exception
, never throw int or something else!):If an exception is thrown, it is thrown. The object that failed to destruct is obviously not properly destroyed, and neither are the ones remaining in the array.
If you use a vector, the problem is the same, just not in your code. :-)
So, throwing destructors is just a Bad Idea(tm).
Like @Martin shows below, the object that did thrown is formally non-existent as soon as we enter the destructor. The others might have their memory reclaimed as well.
However, it obviously contained some complicated things that were not properly of flusher flushed. If that object, and the others following it in the array, contained some mutex locks, open files, database caches, or shared_ptrs, and none of those had their destructors run, we are likely in BIG trouble.
Having std::terminate called at that point, to put the program out of its misery, seems like something you would wish for!