Object destruction versus finalization

Florian santa at nortpole.org
Tue Nov 12 14:40:24 PST 2013


On Tuesday, 12 November 2013 at 20:29:13 UTC, Dicebot wrote:
> On Tuesday, 12 November 2013 at 20:15:02 UTC, Florian wrote:
>> I played around a little and figured out, that destructors in 
>> D work quite similarily to destructors in C++. They are 
>> invoked, after the members of the instance being destructed 
>> have been destroyed themselfes (or at least have been brought 
>> into an invalid state). Therefore, these members cannot be 
>> accessed savely from inside the destructor.
>
> What made you think so? It must be other way around. Destructor 
> is expected to release resources held by object, it is 
> necessary that those resources are still valid at destructor 
> call point. It would have been completely against the mode of 
> operations of garbage collector.

Let me explain this by discussing the example below. I created 
method stubs, which write single lines to the console, so it is 
quite easy to follow the control flow.

The main method creates an instance of a type "Session", which 
itself has a member of type "Connection". Let us assume, that I 
want to properly shutdown the "Connection" instance by invoking 
its methods, when the "Session" is torn down. The example below 
prints the following output:
     ~Connection
     ~Session
     segmentation fault
This means, the destructor of "Connection" is invoked *BEFORE* 
the destructor of "Session" is called. This yields to an invalid 
reference for the call of the shutdown() method, leading to the 
segmentation fault. Of course, in a scenario as simple as that, 
it would be possible to move the shutdown() sequence into the 
destructor of the "Connection" class. However, doing so is not 
desirable. Just picture, that we want to set some timeout 
parameters or the like for the shutdown depending on the state of 
the "Session". This would become really messy. And be assured, I 
have a more complex scenario, where I definitely want to invoke 
methods on memeber instances when an instance is destroyed. I am 
convinced there is a reason for finalizing objects like Java, C# 
and managed C++ do.

Example:

import std.stdio;

class Connection {
	this() { }
	void shutdown() { writeln("shutdown"); }
	~this() { writeln("~Connection"); }
}

class Session {
	Connection connection;
	this() { connection = new Connection(); }
	~this() {
		writeln("~Session");
		connection.shutdown();  // -> segmentation fault
	}
}

void main() { auto session = new Session(); }


More information about the Digitalmars-d-learn mailing list