Thread overview
Strange destructors' call order
Sep 30, 2016
unDEFER
Sep 30, 2016
Adam D. Ruppe
Sep 30, 2016
unDEFER
September 30, 2016
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!
September 30, 2016
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.

September 30, 2016
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.