Looking for an answer for C# and C++. (in C#, replace 'destructor' with 'finalizer')
-
I think the thing to do here is set up a throw-away project (or two: one per langauge) and do a check to find out. – Joel Coehoorn Oct 09 '08 at 19:03
-
1The joy of compiling from the command-line is you don't need to set up a project. Just load up a file in a text editor, compile very easily, and run :) – Jon Skeet Oct 09 '08 at 19:08
-
3@loyc-etc, C++ and C# are pretty different in their semantics. This is really two separate questions. – Onorio Catenacci Oct 09 '08 at 19:39
8 Answers
It does for C# (see code below) but not for C++.
using System;
class Test
{
Test()
{
throw new Exception();
}
~Test()
{
Console.WriteLine("Finalized");
}
static void Main()
{
try
{
new Test();
}
catch {}
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
This prints "Finalized"

- 1,421,763
- 867
- 9,128
- 9,194
-
-
I thought ~Test was a finalizer in C#, not a destructor? Ah I see the ~ syntax is sugar for setting up a finalizer. In the case that my ctor could throw, I expect I'd want to manually add the finalizer as the last step of the ctor to avoid cleaning up non-existent messes. – Logan Capaldo Mar 14 '09 at 22:05
-
@Logan: It depends on which version of the C# spec you read as to whether they call it "finalizer" or "destructor". – Jon Skeet Mar 14 '09 at 23:03
-
@Jon: Is there any other C# specification than Ecma-334? I know they exist, in fact they are published on your website ( http://csharpindepth.com/articles/chapter1/Specifications.aspx ) I mean ... Too bad there are no *Standard* specifications for versions higher than 2.0. That said (protest) ... The semantic of C# Finalizer is not like C++ Destructor (Obviously, you know it). In the C# example I think more appropriate to replace the Finalizer for a Disposer. – Fernando Pelliccioni Feb 26 '13 at 20:21
-
@FernandoPelliccioni: No, there isn't a later version of the ECMA spec than that. As for disposal - the question *specifically* asks about a finalizer. Changing it to use disposal wouldn't answer the question. – Jon Skeet Feb 26 '13 at 20:24
Preamble: Herb Sutter has a great article on the subject:
http://herbsutter.wordpress.com/2008/07/25/constructor-exceptions-in-c-c-and-java/
C++ : Yes and No
While an object destructor won't be called if its constructor throws (the object "never existed"), the destructors of its internal objects could be called.
As a summary, every internal parts of the object (i.e. member objects) will have their destructors called in the reverse order of their construction. Every thing built inside the constructor won't have its destructor called unless RAII is used in some way.
For example:
struct Class
{
Class() ;
~Class() ;
Thing * m_pThing ;
Object m_aObject ;
Gizmo * m_pGizmo ;
Data m_aData ;
}
Class::Class()
{
this->m_pThing = new Thing() ;
this->m_pGizmo = new Gizmo() ;
}
The order of creation will be:
- m_aObject will have its constructor called.
- m_aData will have its constructor called.
- Class constructor is called
- Inside Class constructor, m_pThing will have its new and then constructor called.
- Inside Class constructor, m_pGizmo will have its new and then constructor called.
Let's say we are using the following code:
Class pClass = new Class() ;
Some possible cases:
Should m_aData throw at construction, m_aObject will have its destructor called. Then, the memory allocated by "new Class" is deallocated.
Should m_pThing throw at new Thing (out of memory), m_aData, and then m_aObject will have their destructors called. Then, the memory allocated by new Class is deallocated.
Should m_pThing throw at construction, the memory allocated by "new Thing" will be deallocated. Then m_aData, and then m_aObject will have their destructors called. Then, the memory allocated by new Class is deallocated.
Should m_pGizmo throw at construction, the memory allocated by "new Gizmo" will be deallocated. Then m_aData, and then m_aObject will have their destructors called. Then, the memory allocated by new Class is deallocated. Note that m_pThing leaked
If you want to offer the Basic Exception Guarantee, you must not leak, even in the constructor. Thus, you'll have to write this this way (using STL, or even Boost):
struct Class
{
Class() ;
~Class() ;
std::auto_ptr<Thing> m_pThing ;
Object m_aObject ;
std::auto_ptr<Gizmo> m_pGizmo ;
Data m_aData ;
}
Class::Class()
: m_pThing(new Thing())
, m_pGizmo(new Gizmo())
{
}
Or even:
Class::Class()
{
this->m_pThing.reset(new Thing()) ;
this->m_pGizmo.reset(new Gizmo()) ;
}
if you want/need to create those objects inside the constructor.
This way, no matter where the constructor throws, nothing will be leaked.
-
Another scenario, should m_pGizmo throw at new, m_pThing still leaks right? Thanks.. – krebstar Feb 25 '09 at 04:29
-
No, because m_pThing is a smart pointer. If m_pThing did construct correctly, its destructor will be called if m_pGizmo throws. – paercebal Jul 29 '09 at 23:10
-
Herb Sutter's article is wrong for C# and Java. The finalizers appear to be run even if the constructors throw an exception. – David Leonard Sep 15 '09 at 00:53
-
@David Leonard: You're wrong for C#. I'm not a C# lawyer, but with some Googling, I found the following article which says the construction of a C# object is OUTSIDE the implicit try/finally of the "using" statement. Thus, the Dispose method is NOT called. See: http://www.codeproject.com/KB/cs/tinguusingstatement.aspx and http://msdn.microsoft.com/en-us/library/aa664736.aspx – paercebal Sep 16 '09 at 18:46
-
@David Leonard: You're ALMOST wrong for Java, as Herb Sutter's article places the construction of the object outside the try/finally, doing manually in Java what is automated in C#. I guess you could declare the reference outside, and write the new inside the try/finally, but there must be some reason why it is not done. A little research, though, will reveal that one should avoid using finalize() in Java because its execution can't be relied upon. I am not a Java lawyer, so I have no fast answer. – paercebal Sep 16 '09 at 19:02
-
-
@Travis : You're right. As Sutter's article is about disposers, not finalizers,when David Leonard was writing "*Sutter's article was wrong, The finalizers appear to be run even if the constructors throw an exception*", I wrongly assumed he messed up names (thus, my answer about C# disposers, or Java's finally clause in Sutter's example). The good thing is that your comment gave me the occasion to read the ulterior comments on Sutter's about finalizer executing even when the constructors throws: Another reason to not use them... – paercebal Apr 16 '12 at 19:31
The destructor of the class still being constructed is not called, because the object was never fully constructed.
However, the destructor of its base class (if any) IS called, because the object was constructed as far as being a base class object.
Moreover, any member variables will have their destructors called too (as others have noted).
NB: this applies to C++

- 62,604
- 14
- 116
- 151
-
"destructors of all base classes", to be pedantic. The standard has a whole lot of words how it works in MI when one ctor throws. – MSalters Oct 10 '08 at 14:32
In C++, the answer is no - object's destructor is not called.
However, the destructors of any member data on the object will be called, unless the exception was thrown while constructing one of them.
Member data in C++ is initialized (i.e. constructed) in the same order as it is declared, so when the constructor throws, all member data that has been initialized - either explicitly in the Member Initialization List (MIL) or otherwise - will be torn down again in reverse order.

- 14,677
- 7
- 51
- 61
-
But it should be noted that a raw pointer member which may have been initialized using new will *not* be automatically deleted. – Michael Burr Oct 09 '08 at 22:00
-
He's quite correct actually. If you have a `T*` member initialized with `new T`, then you actually have two objects: the new'ed T and the `T*` itself. Like an `int`, a `T*` has no destructor. Hence, when the `T*` member is deleted, the T pointed to is not. – MSalters Oct 10 '08 at 14:38
-
Agreed. The task of deleting that pointer normally belongs in the destructor, and since the destructor is not called, there's a memory leak (unless a try/catch is written within the constructor to take care of this). The safer alternative is to use auto pointers or smart pointers. – Matt Dillard Oct 10 '08 at 18:02
If the constructor doesn't finish executing, the object doesn't exist, so there's nothing to destruct. This is in C++, I have no idea about C#.

- 35,641
- 17
- 67
- 94
For C++ this is addressed in a previous question: Will the below code cause memory leak in c++
Since in C++ when an exception is thrown in a constructor the destructor does not get called, but dtors for the object's members (that have been constructed) do get called, this is a primary reason to use smart pointer objects over raw pointers - they are a good way to prevent memory leaks in a situation like this.

- 1
- 1

- 333,147
- 50
- 533
- 760
C++ -
Nope. Destructor is not called for partially constructed objects. A Caveat: The destructor will be called for its member objects which are completely constructed. (Includes automatic objects, and native types)
BTW - What you're really looking for is called "Stack Unwinding"
-
Actually, I'm writing an STL-style collection, so I call constructors and destructors manually. Therefore I was wondering whether it's normal to call the destructor in case of an exception. But this "partial destruction" you describe must be done by the compiler, so I don't have to. – Qwertie Oct 09 '08 at 19:32
Don't do things that cause exceptions in the constructor.
Call an Initialize() after the constructor that can throw exceptions.

- 12,390
- 20
- 65
- 92
-
Please, could you explain why? The "Initialize()" idiom is an antipattern in most cases in C++. Perhaps you're mistaking with "don't ever throw an exception from a Destructor?" – paercebal Oct 09 '08 at 19:57
-
I know, designing a class with "Initialize()" beats the purpose of having a class at all. – user15071 Oct 09 '08 at 20:17
-
There are plenty of valid reasons for creating classes with an init method, especially when dealing with concurrency. Sometimes you need object creation to be cheap, even when the primary initialization of that object is expensive. – Herms Oct 09 '08 at 20:25
-
Google's code guidelines discourage using exceptions at all, so they discourage throwing from the constructor ( http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Exceptions ). – Max Lybbert Oct 09 '08 at 22:35
-
On the other hand, pretty much everybody else says to throw from a constructor because that is the only way to signal the constructor failed ( http://herbsutter.wordpress.com/2008/07/25/constructor-exceptions-in-c-c-and-java/ ). – Max Lybbert Oct 09 '08 at 22:37