Thread overview
Does the default opEquals include padding in the comparison? If so, how can the problems that arise with C++ interoperabilty be solved?
Oct 21, 2020
Simon van Bernem
Oct 21, 2020
Paul Backus
Oct 22, 2020
Simon van Bernem
October 21, 2020
I ask this question because I chased a very very nasty bug all the way down, and I think I found the offender:

I have a extern(C++) struct that contains an 8-byte integer followed by a 4-byte enum value. I came across two variables of that type, that are not equal by comparison (no opEquals defined), but when comparing their individual members, all of them are equal. If I inspect the values in the debugger, all members are also equal.

Only the raw memory shows that there is a difference in the 4-byte padding after the enum value. The value that originated from C++ has some bits set, while the one initialized in D code is all zeros. Garbage data in padding is allowed in C++, since the contents of padding is undefined behavior.

The only explanation I can think of is that D memcmps the entire struct including the padding. Is this correct?

If so, what can I do about this? Why doesn't the opEquals get modified appropriately even though the struct is extern(C++)? Can I tell D to only compare the non-padding parts? Or is there a msvc/clang compiler switch to tell them to initialize padding to 0?

I though about using memset 0 all over my C++ code, but that is very error prone, so I am now trying to get rid of all padding in interfacing structs (since there is a warning for that), but that also feels like a workaround, not like solution.
October 21, 2020
On Wednesday, 21 October 2020 at 19:23:43 UTC, Simon van Bernem wrote:
> The only explanation I can think of is that D memcmps the entire struct including the padding. Is this correct?
>
> If so, what can I do about this? Why doesn't the opEquals get modified appropriately even though the struct is extern(C++)? Can I tell D to only compare the non-padding parts? Or is there a msvc/clang compiler switch to tell them to initialize padding to 0?

https://dlang.org/changelog/2.085.0.html#no-cmpsb
October 22, 2020
On Wednesday, 21 October 2020 at 20:10:03 UTC, Paul Backus wrote:
> On Wednesday, 21 October 2020 at 19:23:43 UTC, Simon van Bernem wrote:
>> The only explanation I can think of is that D memcmps the entire struct including the padding. Is this correct?
>>
>> If so, what can I do about this? Why doesn't the opEquals get modified appropriately even though the struct is extern(C++)? Can I tell D to only compare the non-padding parts? Or is there a msvc/clang compiler switch to tell them to initialize padding to 0?
>
> https://dlang.org/changelog/2.085.0.html#no-cmpsb

Thanks! Great to see this was already adressed.