-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Unexpected padding with Auto layout structs #109585
Comments
I tried to mimic the value tuples and how [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
struct S1 { bool Bool; Nullable<int> Num; }
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Auto)]
struct S2 { bool Bool; Nullable<int> Num; }
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
struct S3 { bool Bool; S34 Num; }
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Auto)]
struct S4 { bool Bool; S34 Num; }
struct S34 { bool Bool; int Num; the sequential ones are all 12 bytes, while the auto ones are 16 bytes. |
For completion, I ran
|
CC. @jkotas We've fixed a few issues in the past, related to generics and nullable. This one looks to be a general issue with |
This looks completely expected to me. Types are padded up to the nearest word size. x86 is 32-bit platform, with 4-byte word size. 12 is a multiple of 4. x64 is a 64-bit platform with 8-byte word size. 12 is not a multiple of 8, so it rounds up to 16. 32-bit calculation: 64-bit calculation: [Edit] I'm actually surprised that the sequential layouts are 12 bytes on 64-bit platform. |
As I see it, |
That makes sense. Maybe the auto layout isn't taking into account the alignment of nested types. |
This isn't correct. Types are padded based on the largest natural alignment of all members. The natural alignments are:
The designated packing can be overridden to be smaller, but not larger, than the natural packing. GC tracked types are pointer sized but cannot have the natural packing overridden. Fields that are structs (not primitives) have their own natural alignment based on the members they contain. So |
Is this possibly related to https://stackoverflow.com/questions/67068942/c-sharp-why-do-class-fields-of-struct-types-take-up-more-space-than-the-size-of and https://stackoverflow.com/questions/24742325/why-does-struct-alignment-depend-on-whether-a-field-type-is-primitive-or-user-de? Structs that contain reference types, or used as fields in reference types (classes), are padded more than expected. (I'm not sure if there is already a separate issue for those.) |
The bug you linked is potentially related to the overall issue here, but it wouldn't be related to the fact that you cannot override the natural packing/alignment of GC types.
Typically to achieve this it means you sort fields based on You can optionally also do some sorting within those regions, such as grouping all GC fields together (typically first), or by also sorting by size within a group (so a Notably the .NET auto layout algorithm has historically had some quirks and bugs; some of which we've fixed over time and others of which we've not. I'm not sure where this one in particular falls. |
Description
Looking at the value tuple type
(bool, Nullable<int>)
i expect the following layout:1 byte for the bool + 3 padding bytes
1 byte for the bool of the nullable + 3 padding bytes
4 bytes for the int
which would sum up to 12 bytes,
this however turns into a 16 bytes struct, because 4 bytes of padding are added at the end.
Reproduction Steps
I am using sharplab.io to showcase it:
sharplab.io link
Expected behavior
The struct size should be 12 bytes, but has additionally some trailing 4 byte padding.
Actual behavior
The struct size is 16 bytes because of the trailing 4 byte padding.
The text was updated successfully, but these errors were encountered: