Does the default opEquals include padding in the comparison? If so, how can the problems that arise with C++ interoperabilty be solved?

Simon van Bernem simon.vanbernem at yahoo.de
Wed Oct 21 19:23:43 UTC 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.


More information about the Digitalmars-d-learn mailing list