[Issue 16708] New: opAssign and struct-member padding break comparison and invariants

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Mon Nov 21 05:51:13 PST 2016


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

          Issue ID: 16708
           Summary: opAssign and struct-member padding break comparison
                    and invariants
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Linux
            Status: NEW
          Severity: major
          Priority: P1
         Component: dmd
          Assignee: nobody at puremagic.com
          Reporter: tomerfiliba at gmail.com

When a struct defines an opAssign it is obviously "on its own", but it can't
possibly assign to the padding (which is something built-in assignment does). 

Suppose you get the memory for the struct from a memory-pool and you assign a
value to it directly. The memory was uninitialized at first, but there are no
destructors involved, so there's nothing inherently wrong. Here's an example:


========================================================
import std.stdio;

struct MyShort {
    ushort value;

    void opAssign(MyShort rhs) nothrow @safe @nogc {
        value = rhs.value;
    }
}

struct YourStruct {
    MyShort a;
    int b;
}

void main() {
    YourStruct ys1;
    YourStruct ys2;
    (cast(ubyte*)&ys2)[0 .. YourStruct.sizeof] = 0xff;

    writeln("ys1=", (cast(ubyte*)&ys1)[0 .. YourStruct.sizeof]);
    writeln("ys2=", (cast(ubyte*)&ys2)[0 .. YourStruct.sizeof]);
    // ys1=[0, 0, 0, 0, 0, 0, 0, 0]
    // ys2=[255, 255, 255, 255, 255, 255, 255, 255]

    ys1 = YourStruct(MyShort(17), 18);
    ys2 = YourStruct(MyShort(17), 18);

    writeln("ys1=", (cast(ubyte*)&ys1)[0 .. YourStruct.sizeof]);
    writeln("ys2=", (cast(ubyte*)&ys2)[0 .. YourStruct.sizeof]);
    // ys1=[17, 0, 0, 0, 18, 0, 0, 0]
    // ys2=[17, 0, 255, 255, 18, 0, 0, 0]    <<< does not assign the padding

    writeln(ys1.a == ys2.a);   // true
    writeln(ys1.b == ys2.b);   // true
    writeln(ys1 == ys2);       // false
}
========================================================

So here we get two variables for which memcmp returns != 0, but all their
fields are equal.

--


More information about the Digitalmars-d-bugs mailing list