www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 19122] New: Multiple destruction of union members


          Issue ID: 19122
           Summary: Multiple destruction of union members
           Product: D
           Version: D2
          Hardware: x86
                OS: Windows
            Status: NEW
          Keywords: safe
          Severity: critical
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: simen.kjaras gmail.com

 safe unittest {
    import std.stdio : writeln;
    struct S1 {
        int* p;
        ~this() {
            writeln("Writing garbage to random memory: ", p);
            //*p = 80085;
    struct S2 {
        union {
            S1 a;
            int b;
        int index;
        this(S1 s) {
            a = s;
            index = 0;
        this(int n) {
            b = n;
            index = 1;
    S2 s = 123456;

The above code shows that destructors of union members will be called when the
surrounding struct is destructed. In this case, this leads to reinterpretation
of an int as a pointer, but worse could happen.

If multiple union members have destructors, all of them are called, regardless
of what's currently in the union.

According to https://github.com/dlang/dmd/pull/5830:
"Unrestricted unions can have fields that have destructors, postblits, or
invariants. It's up to the user to call them correctly, the compiler does not
automatically generate calls to them."

This is clearly not what's happening here. Worse, there's no way to tell the
compiler not to call the destructors, short of hiding the actual types behind
ubyte[]/void[] and casting.

As a crowning achievement, this happens in  safe.

Jul 27 2018