www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - _moduleDtor() before gc_term() problem

reply derick_eddington nospam.yashmoo.com writes:
I have a class who's destructor calls an object located at the top-level of an
imported module (the reference is in the static data segment; it's instantiated
in the module constructor and explicitly delete'd in the module destructor
because the object destructor must be run).  The problem is the module
destructor is being called before the client-class's destructor so the
module-object is null when the client-class's destructor uses it, resulting in
seg-fault.  I think this is happening because phobos/internal/dmain2.d calls
_moduleDtor() before gc_term().

This seems very inconvenient to me that modules are destructed before the GC
collects/destructs the remaining objects because it seems to me those objects'
destructors should be able to relying on using module services.

I want to provide a standard object instance at module-level, and I must be
certain that instance is destructed so I have to use explicit delete in the
module destructor.  This standard object allocates and deallocates resources for
clients and client objects need to use it in their destructors to deallocate.
Doesn't this seem like it should be possible?  Am I missing something?
Suggestions?

For example:

framework.d:
------------
# import std.stdio;
#
# StandardObj standardObj;
#
# static this()
# {
#     standardObj = new StandardObj;
# }
#
# static ~this()
# {
#     writefln("%s ~this()", __FILE__);
#     delete standardObj;
# }
#
# class StandardObj
# {
#     void useIt ()
#     {
#          writefln("%s.useIt()", this);
#     }
#
#     ~this()
#     {
#         writefln("%s.~this()", this);
#     }
# }
-------------------------------------

myapp.d:
-------
# import std.stdio;
# import framework;
#
# class MyThing
# {
#     ~this ()
#     {
#         writefln("%s.~this()", this);
#         framework.standardObj.useIt();  // null reference, seg fault
#     }
# }
#
# void main ()
# {
#     MyThing myThing = new MyThing;
# }
---------------------------------------------

$ dmd myapp.d framework.d
$ ./myapp
framework.d ~this()
StandardObj.~this()
MyThing.~this()
Segmentation fault
May 17 2005
next sibling parent "Andrew Fedoniouk" <news terrainformatica.com> writes:
*I think* that in any casy relying on order of deletion
of objects under any GC is not a good decision.
In case of such conglomerate of objects I would consider
its explicit destruction e.g. at the end of main or in module ctor.
This needs such objects to be linked somehow - to be able to run
through all of them and do some finalization (if design cannot be
changed to avoid such dependencies).

Andrew.

<derick_eddington nospam.yashmoo.com> wrote in message 
news:d6ees9$1a6r$1 digitaldaemon.com...
I have a class who's destructor calls an object located at the top-level of 
an
 imported module (the reference is in the static data segment; it's 
 instantiated
 in the module constructor and explicitly delete'd in the module destructor
 because the object destructor must be run).  The problem is the module
 destructor is being called before the client-class's destructor so the
 module-object is null when the client-class's destructor uses it, 
 resulting in
 seg-fault.  I think this is happening because phobos/internal/dmain2.d 
 calls
 _moduleDtor() before gc_term().

 This seems very inconvenient to me that modules are destructed before the 
 GC
 collects/destructs the remaining objects because it seems to me those 
 objects'
 destructors should be able to relying on using module services.

 I want to provide a standard object instance at module-level, and I must 
 be
 certain that instance is destructed so I have to use explicit delete in 
 the
 module destructor.  This standard object allocates and deallocates 
 resources for
 clients and client objects need to use it in their destructors to 
 deallocate.
 Doesn't this seem like it should be possible?  Am I missing something?
 Suggestions?

 For example:

 framework.d:
 ------------
 # import std.stdio;
 #
 # StandardObj standardObj;
 #
 # static this()
 # {
 #     standardObj = new StandardObj;
 # }
 #
 # static ~this()
 # {
 #     writefln("%s ~this()", __FILE__);
 #     delete standardObj;
 # }
 #
 # class StandardObj
 # {
 #     void useIt ()
 #     {
 #          writefln("%s.useIt()", this);
 #     }
 #
 #     ~this()
 #     {
 #         writefln("%s.~this()", this);
 #     }
 # }
 -------------------------------------

 myapp.d:
 -------
 # import std.stdio;
 # import framework;
 #
 # class MyThing
 # {
 #     ~this ()
 #     {
 #         writefln("%s.~this()", this);
 #         framework.standardObj.useIt();  // null reference, seg fault
 #     }
 # }
 #
 # void main ()
 # {
 #     MyThing myThing = new MyThing;
 # }
 ---------------------------------------------

 $ dmd myapp.d framework.d
 $ ./myapp
 framework.d ~this()
 StandardObj.~this()
 MyThing.~this()
 Segmentation fault

 

May 17 2005
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Wed, 18 May 2005 04:04:25 +0000 (UTC),
derick_eddington nospam.yashmoo.com wrote:

 I have a class who's destructor calls an object located at the top-level of an
 imported module (the reference is in the static data segment; it's instantiated
 in the module constructor and explicitly delete'd in the module destructor
 because the object destructor must be run).  The problem is the module
 destructor is being called before the client-class's destructor so the
 module-object is null when the client-class's destructor uses it, resulting in
 seg-fault.  I think this is happening because phobos/internal/dmain2.d calls
 _moduleDtor() before gc_term().
 
 This seems very inconvenient to me that modules are destructed before the GC
 collects/destructs the remaining objects because it seems to me those objects'
 destructors should be able to relying on using module services.

I don't think that the GC is the problem here. If you don't explicitly delete the 'standardObj' then the GC doesn't even call that object's dtor. It is the explicit delete that is nullifying the standardObj instance. That and the fact that the module dtors are called before the MyThing dtor.
 I want to provide a standard object instance at module-level, and I must be
 certain that instance is destructed so I have to use explicit delete in the
 module destructor.  This standard object allocates and deallocates resources
for
 clients and client objects need to use it in their destructors to deallocate.
 Doesn't this seem like it should be possible?  Am I missing something?
 Suggestions?

If you use the 'auto' keyword on the MyThing instance, the D will call its dtor as soon as it goes out of scope, which is before any module dtors get called. Reworked example: framework.d: ------------ import std.stdio; StandardObj standardObj; static this() { writefln("new %s", __FILE__); standardObj = new StandardObj; } static ~this() { writefln("Enter %s ~this()", __FILE__); delete standardObj; writefln("Exit %s ~this()", __FILE__); } class StandardObj { this() { writefln("new StandardObj"); } void useIt () { writefln("%s.useIt()", this); } ~this() { writefln("%s.~this()", this); } } ------------------------------------- myapp.d: ------- import std.stdio; import framework; static this() { writefln("new %s", __FILE__); } static ~this() { writefln("%s ~this()", __FILE__); } class MyThing { this() { writefln("new MyThing"); } ~this () { writefln("%s.~this()", this); framework.standardObj.useIt(); } } void main () { auto MyThing myThing = new MyThing; } --------------------------------------------- C:\temp>build myapp Path and Version : z:\util\build.exe v2.08(935) built on Tue May 17 14:34:07 2005 z:\dmd\bin\..\..\dm\bin\link.exe myapp+framework,myapp.exe,,user32+kernel32,myapp.def/noi; C:\temp>myapp new framework.d new StandardObj new myapp.d new MyThing MyThing.~this() StandardObj.useIt() myapp.d ~this() Enter framework.d ~this() StandardObj.~this() Exit framework.d ~this() C:\temp> -- Derek Melbourne, Australia 18/05/2005 2:49:57 PM
May 17 2005
parent derick_eddington nospam.yashmoo.com writes:
In article <1k520ou5lu21t$.1f8in1jvvfoqd$.dlg 40tude.net>, Derek Parnell says...
If you use the 'auto' keyword on the MyThing instance, the D will call its
dtor as soon as it goes out of scope, which is before any module dtors get
called.

'auto', of course! I totally forgot about that. I need to read through all the docs again, and this should have been in digitalmars.D.learn :) Thanks!
May 18 2005