Note that there are some explanatory texts on larger screens.

plurals
  1. POLayoutKind.Sequential not followed when substruct has LayoutKind.Explicit
    primarykey
    data
    text
    <p>When running this code:</p> <pre><code>using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace StructLayoutTest { class Program { unsafe static void Main() { Console.WriteLine(IntPtr.Size); Console.WriteLine(); Sequential s = new Sequential(); s.A = 2; s.B = 3; s.Bool = true; s.Long = 6; s.C.Int32a = 4; s.C.Int32b = 5; int* ptr = (int*)&amp;s; Console.WriteLine(ptr[0]); Console.WriteLine(ptr[1]); Console.WriteLine(ptr[2]); Console.WriteLine(ptr[3]); Console.WriteLine(ptr[4]); Console.WriteLine(ptr[5]); Console.WriteLine(ptr[6]); Console.WriteLine(ptr[7]); //NB! Console.WriteLine("Press any key"); Console.ReadKey(); } [StructLayout(LayoutKind.Explicit)] struct Explicit { [FieldOffset(0)] public int Int32a; [FieldOffset(4)] public int Int32b; } [StructLayout(LayoutKind.Sequential, Pack = 4)] struct Sequential { public int A; public int B; public bool Bool; public long Long; public Explicit C; } } } </code></pre> <p><strong>I expect this output BOTH on x86 and x64:</strong> <br><em>4 or 8</em> (depending on x86 or x64) <br> <br>2 <br>3 <br>1 <br><strong>6</strong> <br><strong>0</strong> <br>4 <br>5 <br><em>garbage</em></p> <p><strong>What I get instead on x86:</strong> <br>4 <br> <br><strong>6</strong> <br><strong>0</strong> <br>2 <br>3 <br>1 <br>4 <br>5 <br><em>garbage</em></p> <p><strong>What I get instead on x64:</strong> <br>8 <br> <br><strong>6</strong> <br><strong>0</strong> <br>2 <br>3 <br>1 <br><strong>0</strong> <br>4 <br>5</p> <p><strong>More:</strong> <br><strong>- The problem goes away when I remove the LayoutKind.Explicit and FieldOffset attributes.</strong> <br>- The problem goes away when I remove the Bool field. <br>- The problem goes away when I remove the Long field. <br>- Note that on x64 it seems that the Pack=4 attribute parameter is ignored too?</p> <p>This applies in .Net3.5 and also .Net4.0</p> <p><strong>My question: what am I missing? Or is this a bug?</strong> <br>I found a similar question: <br><a href="https://stackoverflow.com/questions/4132533/why-does-layoutkind-sequential-work-differently-if-a-struct-contains-a-datetime">Why does LayoutKind.Sequential work differently if a struct contains a DateTime field?</a> <br>But in my case the layout changes even when the attribute of the substruct changes, without any changes to data types. So it does not look like an optimization. Besides that, I would like to point out that the other question is still unanswered. <br>In that other question they mention that the layout is respected when using Marshalling. I havent tested that myself but I wonder why is the layout not respected for unsafe code, since all the relevant attributes seem to be in place? Does the documentation mention somewhere that these attributes are ignored unless Marshalling is done? Why? <br>Considering this, can I even expect LayoutKind.Explicit to work reliably for unsafe code? <br>Moreover, the documentation mentions the motive of keeping structs with expected layout: </p> <blockquote> <p>To reduce layout-related problems associated with the Auto value, C#, Visual Basic, and C++ compilers specify Sequential layout for value types.</p> </blockquote> <p><br>But this motive apparently does not apply to unsafe code?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload