Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alignment of members & size of structs inconsistent with C #19520

Open
dlangBugzillaToGithub opened this issue Dec 26, 2018 · 2 comments
Open
Labels
Arch:x86_64 Issues specific to x86_64 P3 Severity:normal

Comments

@dlangBugzillaToGithub
Copy link

dbohlender reported this on 2018-12-26T15:36:46Z

Transferred from https://issues.dlang.org/show_bug.cgi?id=19516

CC List

  • kinke

Description

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
", (void*)&s.b-(void*)&s);

    // Yields size 32, unlike the 24 in D
    printf("size of s: %lu
", sizeof(s));
}
--

[1] https://dlang.org/spec/struct.html#struct_layout
[2] https://dpaste.dzfl.pl/ff55c816a940
[3] https://www.jdoodle.com/a/Sgc
@dlangBugzillaToGithub
Copy link
Author

kinke commented on 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

@dlangBugzillaToGithub
Copy link
Author

issues.dlang (@jmdavis) commented on 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Arch:x86_64 Issues specific to x86_64 P3 Severity:normal
Projects
None yet
Development

No branches or pull requests

1 participant