digitalmars.D.bugs - [Issue 16708] New: opAssign and struct-member padding break
- via Digitalmars-d-bugs (53/53) Nov 21 2016 https://issues.dlang.org/show_bug.cgi?id=16708
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 puremagic.com Reporter: tomerfiliba 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. --
Nov 21 2016