www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - When is a class's destructor called?

reply "Mike" <none none.com> writes:
I'm trying to implement a very minimal D runtime for the ARM 
Cortex-M platform.  I've been quite successful so far, but I'm 
now getting into reference types and I need to understand better 
what D does under the hood.

I have a working malloc/free implementation, but don't have a 
garbage collector.  I'm not yet sure if I want a garbage 
collector, so at the moment, I'm trying to implement something 
simple.

Consider the following code modeled after the example at 
http://dlang.org/memory.html#newdelete:

*************************************
class X
{
     __gshared uint _x;

     new(size_t nBytes)
     {
	Trace.WriteLine("Constructing");
	
         void* p;

         p = malloc(nBytes);

         if (p == null)
         {
	    //TODO:
             //throw new OutOfMemoryError();
         }

         return p;
     }

     ~this()
     {
	Trace.WriteLine("Destructor");
     }

     delete(void* p)
     {
         if (p != null)
         {
             free(p);
         }

         Trace.WriteLine("Destroying");
     }
}

void DoX()
{
     X x = new X();
     x._x = 123;
     Trace.WriteLine(x._x);

     //Why doesn't x's destructor get called here.
}

//My entry point
void main()
{
     DoX();

     Trace.WriteLine("Done");
     while(true) { }
}
**************************************

The output is as follows:
------------------------------
Constructing
56
Done

x's destructor never gets called.  What do I need to implement to 
have the destructor called when x goes out of scope?

I'm using GDC 4.8 cross-compiled for arm-none-eabi on a Linux 
64-bit host.

Thanks,
Mike
Dec 28 2013
parent reply Mike Parker <aldacron gmail.com> writes:
On 12/29/2013 2:03 PM, Mike wrote:

 x's destructor never gets called.  What do I need to implement to have
 the destructor called when x goes out of scope?
Class destructors are not called when an object goes out of scope. They are called by the garbage collector only when memory needs to be reclaimed or during the cleanup cycle during app shutdown.
Dec 28 2013
parent reply "Mike" <none none.com> writes:
On Sunday, 29 December 2013 at 06:53:08 UTC, Mike Parker wrote:
 On 12/29/2013 2:03 PM, Mike wrote:

 x's destructor never gets called.  What do I need to implement 
 to have
 the destructor called when x goes out of scope?
Class destructors are not called when an object goes out of scope. They are called by the garbage collector only when memory needs to be reclaimed or during the cleanup cycle during app shutdown.
Ok, I understand that, but since I don't have a garbage collector, what must I implement to call the destructor when it goes out of scope? Another way of asking the question is: How does the garbage collector know when something has gone out of scope and is therefore safe to collect? And where is that implemented in the runtime?
Dec 28 2013
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Mike:

 How does the garbage collector know when something has gone out 
 of scope
The garbage collector doesn't know that. Look in Wikipedia how a Mark&Sweep GC works. Bye, bearophile
Dec 29 2013
prev sibling next sibling parent reply "ponce" <contact gam3sfrommars.fr> writes:
 Ok, I understand that, but since I don't have a garbage 
 collector, what must I implement to call the destructor when it 
 goes out of scope?

 Another way of asking the question is: How does the garbage 
 collector know when something has gone out of scope and is 
 therefore safe to collect?  And where is that implemented in 
 the runtime?
If you want deterministic destruction, you have plenty of choices: - scoped! - using structs instead - scope(exit) - RefCounted! - Unique! - ... Yet using classes for ressources is not composable. It's either: - using classes for the convenience and deal with resource release manually - using structs It's an open quesiton for me which choice is best.
Dec 29 2013
next sibling parent "Dicebot" <public dicebot.lv> writes:
Also destructors are not guaranteed to be run by D specification. 
It is perfectly legal to skip such cleanup step upon program 
termination.

http://dlang.org/class.html#destructors :

"The garbage collector is not guaranteed to run the destructor 
for all unreferenced objects. Furthermore, the order in which the 
garbage collector calls destructors for unreference objects is 
not specified. This means that when the garbage collector calls a 
destructor for an object of a class that has members that are 
references to garbage collected objects, those references may no 
longer be valid. This means that destructors cannot reference sub 
objects. This rule does not apply to auto objects or objects 
deleted with the DeleteExpression, as the destructor is not being 
run by the garbage collector, meaning all references are valid."
Dec 29 2013
prev sibling parent reply "Mike" <none none.com> writes:
On Sunday, 29 December 2013 at 10:16:33 UTC, ponce wrote:
 If you want deterministic destruction, you have plenty of 
 choices:
 - scoped!
 - using structs instead
 - scope(exit)
 - RefCounted!
 - Unique!
 - ...
Do you happen to know of any clever technique to make object, and everything that inherits from it, a referenced counted object?
Dec 29 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/29/2013 04:00 AM, Mike wrote:
 On Sunday, 29 December 2013 at 10:16:33 UTC, ponce wrote:
 If you want deterministic destruction, you have plenty of choices:
 - scoped!
 - using structs instead
 - scope(exit)
 - RefCounted!
 - Unique!
 - ...
Do you happen to know of any clever technique to make object, and everything that inherits from it, a referenced counted object?
There is std.typecons.RefCounted: Ali
Dec 29 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Ali Çehreli:

 On 12/29/2013 04:00 AM, Mike:
 Do you happen to know of any clever technique to make object, 
 and
 everything that inherits from it, a referenced counted object?
There is std.typecons.RefCounted:
I think it only works on a single object, not on the whole tree. (And I think RefCounted is not used often in D.) Bye, bearophile
Dec 29 2013
parent "Mike" <none none.com> writes:
On Sunday, 29 December 2013 at 14:24:05 UTC, bearophile wrote:
 Ali Çehreli:

 On 12/29/2013 04:00 AM, Mike:
 Do you happen to know of any clever technique to make object, 
 and
 everything that inherits from it, a referenced counted object?
There is std.typecons.RefCounted:
I think it only works on a single object, not on the whole tree. (And I think RefCounted is not used often in D.) Bye, bearophile
Yep, and it's a struct, so no inheritance.
Dec 29 2013
prev sibling parent "Dicebot" <public dicebot.lv> writes:
On Sunday, 29 December 2013 at 06:58:03 UTC, Mike wrote:
 Ok, I understand that, but since I don't have a garbage 
 collector, what must I implement to call the destructor when it 
 goes out of scope?
Patch compiler to make all classes scope classes. But that won't be D anymore.
Dec 29 2013