[Issue 14229] New: RAII ordering is wrong

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Fri Feb 27 12:57:59 PST 2015


https://issues.dlang.org/show_bug.cgi?id=14229

          Issue ID: 14229
           Summary: RAII ordering is wrong
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Windows
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: DMD
          Assignee: nobody at puremagic.com
          Reporter: etcimon at gmail.com

I'm having issues with the ordering of copy constructors / destructors, and
this causes my reference counting utilities to break down.

Here's the relevant code:

```
import std.stdio;

struct A {
        this(B!"A->" i) {
                b = i;
                writeln("A.__ctor");
        }
        ~this() { writeln("A.__dtor"); }
        this(this) { writeln("A.__copy"); }
        B!"A->" b;
}

struct B(string ident) {
        this(C!"B1->" i, C!"B2->" j, C!"B3->" k) {
                c = i;
                c2 = j;
                c3 = k;
                writeln(ident ~ "B.__ctor");
        }
        ~this() { writeln(ident ~ "B.__dtor"); }
        this(this) { writeln(ident ~ "B.__copy"); }
        C!"B1->" c;
        C!"B2->" c2;
        C!"B3->" c3;
}

struct C(string ident) {
        this(int i, int j, int k) {
               a = i;
               b = j;
               c = k;
               writeln(ident ~ "C.__ctor");
        }

        ~this() { writeln(ident ~ "C.__dtor"); }
        this(this) { writeln(ident ~ "C.__copy"); }
        int a;
        int b;
        int c;
}

C!"B1->" getC(A a) {
        C!"B1->" c = a.b.c;
        writeln("Returning B1->C");
        return c;
}



void main() {
        A a;
        C!"B1->" c1 = C!"B1->"(1,2,3);
        C!"B2->" c2 = C!"B2->"(4,5,6);
        C!"B3->" c3 = C!"B3->"(7,8,9);
        B!"A->" b = B!"A->"(c1, c2, c3);
        a.b = b;

        writeln("Getting C");

        C!"B1->" c;
        c = getC(a);
        writeln("Got C");
}
```

The relevant output is:

----

Getting C
B1->C.__copy
B2->C.__copy
B3->C.__copy
A->B.__copy
A.__copy
B1->C.__copy
Returning B1->C
A.__dtor
A->B.__dtor
B3->C.__dtor
B2->C.__dtor
B1->C.__dtor
B1->C.__dtor
Got C

----

There's a mistake here.

The copy pattern under "Getting C" is fine. From the top down. To be equally
fine, destruction pattern should reverse it! It should propagate the
destruction tree from the bottom up. ie. you should be seeing:

B3->C.__dtor
B2->C.__dtor
B1->C.__dtor
A->B.__dtor
A.__dtor

Unfortunately, this might end up in the early destruction of an object
(segfault), and an absolute nightmare for the poor programmer debugging this
while expecting a bottom up destruction pattern.

--


More information about the Digitalmars-d-bugs mailing list