www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Strange destructors' call order

reply unDEFER <undefer gmail.com> writes:
Hello again!
I have strange destructors' call order in the next code:

$ cat dub.json
=============================8<=========================
{
     "name": "test",
     "dependencies": {
         "bdb2d": ">=5.3.28",
     }
}
=============================>8=========================

$ cat source/main.d
=============================8<=========================
module global_state;

import std.stdio;
import std.file;
import std.string;
import std.conv;
import core.stdc.stdlib;
import berkeleydb.all;

class GlobalState
{
     DbEnv dbenv;
     Db db_map;

     this()
     {
         try{
             mkdir("/tmp/bdb/");
         } catch (FileException file)
         {
         }

         dbenv = new DbEnv(0);

         uint env_flags = DB_CREATE |
                     DB_INIT_LOCK |
                     DB_INIT_LOG  |
                     DB_INIT_MPOOL;

         dbenv.open("/tmp/bdb", env_flags, octal!666);

         db_map = new Db(dbenv, 0);
         db_map.open(null, "map.db", null, DB_BTREE, DB_CREATE /*|
                         DB_AUTO_COMMIT | DB_MULTIVERSION*/, 
octal!600);
     }

     ~this()
     {
         writefln("CLOSE db_map");
         db_map.close();
         writefln("CLOSE dbenv");
         dbenv.close();
     }
}

void main()
{
     GlobalState gs = new GlobalState();
}
=============================>8=========================

The program doesn't show "CLOSE db_map", "CLOSE dbenv", but calls 
dbenv and db_map destructors. And it falls with message "Program 
exited with code -11".

So destructors of child objects called earlier than destructor of 
the parent object.
Why it so here, if in the next more simple code it's working as 
expected:
=============================8<=========================
#!/usr/bin/rdmd

import std.stdio;

class B
{
     int a;

     ~this()
     {
         writefln("~B");
     }
}

class A
{
     B b;

     this()
     {
         b = new B();
     }

     ~this()
     {
         writefln("%d", b.a);
         writefln("~A");
     }
}

void main()
{
     A a = new A();
}
=============================>8=========================

It prints:
0
~A
~B

Thank you in advance!
Sep 30 2016
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 30 September 2016 at 21:18:46 UTC, unDEFER wrote:
 So destructors of child objects called earlier than destructor 
 of the parent object.
Since you are letting the garbage collector clean up those classes, it is free to call the destructors in whatever order it deems convenient, since all the objects, parents and children, are considered dead simultaneously. If you need destructor ordering, use structs or explicit create and destroy calls.
Sep 30 2016
parent unDEFER <undefer gmail.com> writes:
On Friday, 30 September 2016 at 21:22:57 UTC, Adam D. Ruppe wrote:
 If you need destructor ordering, use structs or explicit create 
 and destroy calls.
Thank you. destroy(gs) working good for me.
Sep 30 2016