.net - How to get aligned size of CLR blittable struct? -
i making class similar safebuffer targetting .net 2.0. 1 of functions void readarray<t>(long position, t[] array, int offset, int count) (or writearray) reads/writes series of (blittable) structures into/from array.
my first guess use marshal.ptrtostructure/structuretoptr along advancing marshal.sizeof. looking @ il safebuffer.readarray shows uses marshal.alignedsizeof<t>() advancement (an internal method). function defined as:
uint s = marshal.sizeof<t>(); if (s == 1u || s == 2u || intptr.size == 8 && s == 4u) { return s; } return marshal.alignedsizeoftype(typeof(t)); // internalcall that method defined in .net 4.0 unavailable me (and not in rotor).
my idea use marshal.unsafeaddrofpinnedarrayelement on adjacent elements in array didn't work. here testing code:
using system; using system.reflection; using system.runtime.interopservices; namespace test { class program { [structlayout(layoutkind.sequential)] struct { byte a; short x; byte b; } private static methodinfo marshalalignedsizeof; static int malignedsizeof(type t) { if (marshalalignedsizeof == null) { marshalalignedsizeof = typeof(marshal).getmethod("alignedsizeof", bindingflags.nonpublic | bindingflags.static); } return (int)(uint)marshalalignedsizeof.makegenericmethod(t).invoke(null, null); } static int alignedsizeof(type t) { array = array.createinstance(t, 0); gchandle pin = gchandle.alloc(a, gchandletype.pinned); try { return (int)(marshal.unsafeaddrofpinnedarrayelement(a, 1).toint64() - marshal.unsafeaddrofpinnedarrayelement(a, 0).toint64()); } { pin.free(); } } unsafe static void main(string[] args) { console.writeline("sizeof: " + sizeof(a)); console.writeline("sizeof: " + marshal.sizeof(typeof(a))); console.writeline("aligned size: " + alignedsizeof(typeof(a))); console.writeline("mars algn sz: " + malignedsizeof(typeof(a))); } } } which outputs 6, 6, 6,8 on x86 or x64 (notice how native alignedsizeof different?).
so questions are:
- discussion: why aligned size different normal size? in c/c++ sizeof() aligned value. (
sizeof(arr)/sizeof(arr[0])works) - is there managed way (with or without unsafe code) aligned size of blittable generic struct?
- should using
sizeof(), not care alignment? in case doing block-transfer...
you have pick option 3, don't have access structuretoptrnative(). can use marshal.structuretoptr() copy value type value , demands use marshal.sizeof() measure it.
that's buck stops. other questions, exact layout rules clr uses internal storage pretty unusual , hard reverse engineer. size of example structure when stored in array indeed 8, 2 bytes of padding added. 6 required fields aligned properly. no idea why this, buried in clr internals. if want experiment debugger see in practice this answer shows how that.
static void main(string[] args) { var arr = new a[] { new a() { = 1, x = 2, b = 3}, new { = 0x11, x = 0x12, b = 0x13 }}; } // <== set breakpoint here and put "&arr" in debugger memory window's address box
0x000000001d67de70 98 73 14 03 00 00 00 00 01 00 02 00 03 00 00 00 11 00 12 00 13 00 00 00 ^ arr[0] ^ arr[1]
Comments
Post a Comment