C++ vc C#. Destructor of not created class get called.

  • Thread starter Thread starter Daniel O'Connell [C# MVP]
  • Start date Start date
D

Daniel O'Connell [C# MVP]

pronto said:
Hello All.

I've got some unexpected (to me) behavior. In C++, destructor of the class
that wasn't created is not called,
in C# some how I've got destructor call for class that wasn't initialized
properly (by constructor). Please look examples.

Is that a normal ? .. or garbage collector take care of all ?
Am I doing something wrong ?

It can happen. At the moment you create an object, it exists. The
constructor does initialization, but if it throws an exception, you end up
with a partially constructed type which the GC will eventually clean up.
Finalization is also handled by the GC and will always be called for a given
instance, so it *must* be able to deal with partially constructed instances.

In most cases there is no point in using a finalizer, the GC will always
clean up managed memory. You need finalization when you are wrapping
unmanaged resources like file handles. Finalization is something you should
strive to avoid, it can be very expensive and not totally reliable(there are
a small set of circumstances where finalizers may not be run, though they
are rather rare in practice and can be pretty much eliminated with .NET 2.0,
once its released). Look up the IDisposable pattern(its not quite as easy as
RAII, but with the using keyword it works well), joining IDisoposable with
GC.SurpressFinalize can help performance substantially.

Also, if you are interested in why finalization is expensive and a bit of
how it works and feel like reading alot, check out
http://blogs.msdn.com/cbrumme/archive/2004/02/20/77460.aspx (second time
I've linked to that today, LOL).
P.S. I'm new in C#.


C++ output :
------------
C1::C1
C2::C2
C1::~C1
Exception!
Press any key to continue

C# output :
-----------
C1::C1
C2::C2
Exception!
C3::~C3
C2::~C2
C1::~C1
Press any key to continue

C++ code :
----------
class C1
{
public:
C1::C1()
{
puts("C1::C1");
}
virtual C1::~C1()
{
puts("C1::~C1");
}
};

class C2 : public C1
{
public :
C2::C2()
{
puts("C2::C2");
throw "1";
}
virtual C2::~C2()
{
puts("C2::~C2");
}
};

class C3 : public C2
{
public :
C3::C3()
{
puts("C3::C3");
}
virtual C3::~C3()
{
puts("C3::~C3");
}
};

int main(int argc, char* argv[])
{
try
{
C3 c3;
}
catch(...)
{
puts("Exception!");
}

return 0;
}

C# code :
---------
class C1
{
public C1()
{
Console.WriteLine("C1::C1");
}
~C1()
{
Console.WriteLine("C1::~C1");
}
};
class C2 : C1
{
public C2()
{
Console.WriteLine("C2::C2");
throw new Exception("1");
}
~C2()
{
Console.WriteLine("C2::~C2");
}
};
class C3 : C2
{
public C3()
{
Console.WriteLine("C3::C3");
}
~C3()
{
Console.WriteLine("C3::~C3");
}
};

class Class1
{
[STAThread]
static void Main(string[] args)
{
try
{
C3 c3 = new C3();
}
catch(Exception)
{
Console.WriteLine("Exception!");
}
}
}
 
Hello All.

I've got some unexpected (to me) behavior. In C++, destructor of the class
that wasn't created is not called,
in C# some how I've got destructor call for class that wasn't initialized
properly (by constructor). Please look examples.

Is that a normal ? .. or garbage collector take care of all ?
Am I doing something wrong ?

P.S. I'm new in C#.


C++ output :
------------
C1::C1
C2::C2
C1::~C1
Exception!
Press any key to continue

C# output :
-----------
C1::C1
C2::C2
Exception!
C3::~C3
C2::~C2
C1::~C1
Press any key to continue

C++ code :
----------
class C1
{
public:
C1::C1()
{
puts("C1::C1");
}
virtual C1::~C1()
{
puts("C1::~C1");
}
};

class C2 : public C1
{
public :
C2::C2()
{
puts("C2::C2");
throw "1";
}
virtual C2::~C2()
{
puts("C2::~C2");
}
};

class C3 : public C2
{
public :
C3::C3()
{
puts("C3::C3");
}
virtual C3::~C3()
{
puts("C3::~C3");
}
};

int main(int argc, char* argv[])
{
try
{
C3 c3;
}
catch(...)
{
puts("Exception!");
}

return 0;
}

C# code :
---------
class C1
{
public C1()
{
Console.WriteLine("C1::C1");
}
~C1()
{
Console.WriteLine("C1::~C1");
}
};
class C2 : C1
{
public C2()
{
Console.WriteLine("C2::C2");
throw new Exception("1");
}
~C2()
{
Console.WriteLine("C2::~C2");
}
};
class C3 : C2
{
public C3()
{
Console.WriteLine("C3::C3");
}
~C3()
{
Console.WriteLine("C3::~C3");
}
};

class Class1
{
[STAThread]
static void Main(string[] args)
{
try
{
C3 c3 = new C3();
}
catch(Exception)
{
Console.WriteLine("Exception!");
}
}
}
 
Daniel O'Connell said:
It can happen. At the moment you create an object, it exists. The
constructor does initialization, but if it throws an exception, you end up
with a partially constructed type which the GC will eventually clean up.

Assuming there are no references to it. This is ordinarily true, but there
are exceptions (all the ones I know of being pathological.) See
http://groups.google.com/[email protected]#link1
for some examples.
 
Mike Schilling said:
Assuming there are no references to it. This is ordinarily true, but
there
are exceptions (all the ones I know of being pathological.) See
http://groups.google.com/[email protected]#link1
for some examples.

It is quite possible for a reference to become available without being
constructed. I didn't mean to imply that it will never be referenced
anywhere, just that it will be GC'd and finalized just like every other
object, even though it is only partially constructed. Writing code that
actually allows a reference to a partially constructed type generally does
have to be intentional, however. I know of no way to do it without the
object itself choosing to reference itself somewhre(this is a reason why
registering an object in a static collection from a constructor is a *bad*
idea unless its sealed, etc).

Its also quite possible, as the last message in that thread shows, for the
finalizer of a given object to resurrect itself, its just not common.
 
It is quite possible for a reference to become available without being
constructed. I didn't mean to imply that it will never be referenced
anywhere, just that it will be GC'd and finalized just like every other
object, even though it is only partially constructed. Writing code that
actually allows a reference to a partially constructed type generally does
have to be intentional, however. I know of no way to do it without the
object itself choosing to reference itself somewhre(this is a reason why
registering an object in a static collection from a constructor is a *bad*
idea unless its sealed, etc).


Maybe it is a bit OT here, but is there a way to invoke undefined behaviour
when calling a virtual method from within the ctor of an object or calling a
virtual method on a incomplete constucted object?
I tried all stuff but there was never the wrong method called or any
Exception thrown.
 
cody said:
Maybe it is a bit OT here, but is there a way to invoke undefined
behaviour
when calling a virtual method from within the ctor of an object or calling
a
virtual method on a incomplete constucted object?
I tried all stuff but there was never the wrong method called or any
Exception thrown.

There isn't any undefined behaviour that I know of in the *runtime*, the
risk you run when calling a virtual method from a constructor is that the
constructor for the type that overrides that method may not have been called
and it may not have been initalized.
--
cody

[Freeware, Games and Humor]
www.deutronium.de.vu || www.deutronium.tk
 
Back
Top