Bug 19516 – Alignment of members & size of structs inconsistent with C

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
All
Creation time
2018-12-26T15:36:46Z
Last change time
2024-12-13T19:01:44Z
Assigned to
No Owner
Creator
dbohlender
Moved to GitHub: dmd#19520 →

Comments

Comment #0 by issues.dlang — 2018-12-26T15:36:46Z
According to the spec [1], D structs are supposed to have the same memory layout as their C counterparts. However, writing some bindings for a C library I found the following inconsistency. -- D code (see [2]) struct s { union { double d; char[20] cs; }; char b; } pragma(msg, s.b.offsetof); // Expecting 24 but getting 20 pragma(msg, s.sizeof); // Expecting 32 but getting 24 void main(){} -- In C (using clang 7 or gcc 8.1 [3]) the offset of b is 20, but 24 when using dmd/ldc [2]. The mismatching sizeof output seems to be a result of that. -- C code (see [3]) #include <stdio.h> struct S { union { double d; char cs[20]; }; char b; }; int main(){ struct S s; // Yields 24, unlike the 20 in D printf("b at: %lu\n", (void*)&s.b-(void*)&s); // Yields size 32, unlike the 24 in D printf("size of s: %lu\n", sizeof(s)); } -- [1] https://dlang.org/spec/struct.html#struct_layout [2] https://dpaste.dzfl.pl/ff55c816a940 [3] https://www.jdoodle.com/a/Sgc
Comment #1 by kinke — 2018-12-26T16:24:27Z
This is caused by how D treats *anonymous* nested structs and unions - their fields are correctly merged into the containing aggregate (alignment etc. is fine), but the tail padding of that nested struct/union isn't applied to the offsets of the following fields (which is most likely a bug). I.e., this ugly workaround works as expected: struct s { static union U { double d; char[20] cs; } U u; char b; alias u this; } pragma(msg, s.b.offsetof); // 24 pragma(msg, s.sizeof); // 32
Comment #2 by issues.dlang — 2018-12-26T16:56:28Z
(In reply to kinke from comment #1) > This is caused by how D treats *anonymous* nested structs and unions - their > fields are correctly merged into the containing aggregate (alignment etc. is > fine), but the tail padding of that nested struct/union isn't applied to the > offsets of the following fields (which is most likely a bug). > > I.e., this ugly workaround works as expected: > > struct s { > static union U { double d; char[20] cs; } > U u; > char b; > alias u this; > } > pragma(msg, s.b.offsetof); // 24 > pragma(msg, s.sizeof); // 32 Thanks for the quick reply and clarification of the issue. I'll be using the workaround for now.
Comment #3 by robert.schadek — 2024-12-13T19:01:44Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19520 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB