Recently, while taking an introductory unit focused on Object Oriented programming, I was introduced to the Garbage Collector in C#, and that it’s role is to “clean up” objects that are no longer being referenced. Then I was introduced to destructors, and how they’re called just before the object is deleted.
Naturally, I got thinking, but I never remembered to ask the lecturer about it; what will happen if you create an instance of a class within the destructor of the same class?
C# example
class Person{
~Person(){
Person p = new Person();
Console.WriteLine("Person destroyed");
}
}
class Program{
static void Main(string[] args){
Person p = new Person();
}
}
I would like to approach this from a more theoretical point of view, so I’m reluctant (at this stage) to try it since I probably wouldn’t understand anyway, but I have a few theories. Besides, I’m not at my regular computer right now 😉
- Person.~Person() is going to recurse, as each time the new Person is created, it’s going to call its destructor and create a new Person ad infinitum, or until some kind of memory-related exception occurs. Subsequently, main will never terminate.
- The compiler will complain (adding this option to every scenario seems like a good idea anyway).
- Somehow, some kind of “destructor skipping” will occur. ie. object destruction wouldn’t be called sequentially, so neither would the constructor.
Now for a similarly related question. If the Garbage Collector’s role is to delete the objects that are no longer referenced/needed, how would a situation like the one above be handled in an environment without a Garbage Collector – say, C++?
There’s no real mystery here I think.
It won’t ‘recurse’ as such – you’re just chucking a new object on the managed heap which is immediately dereferenced; thus making it a candidate for garbage collection.
Eventually the garbage collector will come round again, triggering the operation again etc.
That’s not recursion – more like a chain. But ultimately each
Personwill be removed from memory.And, after a while the Garbage collector will send you an email complaining that you’re not playing fair.
As for C++, well my guess is a stack overflow, since construction/destruction is happening there and then, and a very sulky computer afterwards.
If your next logical thought is ‘shouldn’t the runtime/language stop this from happening?’ – no. The language or runtimes in question are not there to stop you doing something that would otherwise be considered ill-advised; it trusts you, the programmer, to make sure you’re not doing that.
That said – in an application shutdown scenario (re your comment below) the .Net runtime is going to act out of self-interest and will ultimately stop processing these finalizers to enact a shutdown. Finalizers are for your benefit, not the runtime’s.