-
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
Struct field affects size of derived class #109680
Comments
Seems like the VM is moving the struct field to the end of the object for some reason? |
A question: is |
I'm not entirely sure what this means. The Note this doesn't mean that in the future changes aren't possible. It does mean that the |
From experimenting, StructLayout.Sequential doesn't impact this, the struct will still get reordered to the end of the class by the runtime (IIRC it has the right to do this; the sequential-ness is only guaranteed at marshaling boundaries? I may be misremembering but this is how it worked on netfx too.) If you add an extra uint16 to ObjectWrapper it becomes clearer what might be happening - ObjectWrapper will get rounded up to 2x the size of an object reference, so it gets padding at the end of it before _value appears, and then you potentially have padding after _value. I think the calculation that determines alignment/packing here is not 'seeing through' the struct as desired. It would be nice if it did but I'm not sure you could actually generalize a rule like that without having nasty consequences in cases where you're passing I'd be wary that this could break existing code. |
That does seem like it could be the case both for this issue and at least 2 of the linked issues.
I don't understand. How would passing refs affect it? The struct itself is always at a fixed offset with a fixed size. I don't think it should matter whether the struct is at the beginning of the class or the end.
I agree. In fact, the bug described here seems to violate that. |
The ideal behavior (without context) would be to have no padding anywhere, but in some cases you would need padding. I.e. you have a struct with an ideal size of 3 bytes; the heap allocation if you box it can't be 3 bytes, it will get rounded up to some larger allocation size most likely. So at that point the size of it on the heap and the size of it within an enclosing type have become different and you have to be careful not to accidentally over-read or under-write when doing initialization. You'd also potentially run into problems then with people mixing up the different types of sizeof's, am i using the boxed size when i meant the in-place size? did i mean the marshal size, which might be different from both because it contains a bool? Am I thinking in terms of array layout instead of field layout? etc. I ran into this previously on netfx writing an InlineArray equivalent specialized for 4 elements. The spacing between fields was not what I expected in some cases depending on the element type, and as a result I observed memory corruption when using |
Considering this is for auto layout, I wouldn't even consider the implications of unsafe APIs. |
|
Description
Adding a struct field to a base class makes the derived class larger than expected.
Reproduction Steps
Expected behavior
The type size should be the same whether the field is a reference type, or a struct wrapper around a reference type.
Actual behavior
Regression?
No, the behavior is the same on .Net Framework
Known Workarounds
Don't use struct fields.
Add an additional base type above that type to contain the struct field.
Configuration
Other information
Possibly related to #109585.
Also 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.
The text was updated successfully, but these errors were encountered: