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
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