Это не имеет никакого смысла. Маршаллинг используется для взаимодействия - и при выполнении взаимодействия обе стороны должны согласовать точно о структуре struct
.
При использовании автоматической компоновки вы откладываете решение о компоновке структуры компилятору. Даже разные версии одного и того же компилятора могут привести к разным макетам - это проблема. Например, один компилятор может использовать это:
public struct StructAutoLayout
{
byte B1;
long Long1;
byte B2;
long Long2;
byte B3;
}
в то время как другие могут сделать что-то вроде этого:
public struct StructAutoLayout
{
byte B1;
byte B2;
byte B3;
byte _padding;
long Long1;
long Long2;
}
При работе с машинным/неуправляемым кодом, есть довольно много не мета-данные не участвуют - только указатели и значения. Другая сторона не знает, как структура фактически выложена, ожидает фиксированный макет, о котором вы оба заранее договорились.
. NET имеет тенденцию делать вас испорченными - почти все просто работает. Это не тот случай, когда вы сталкиваетесь с чем-то вроде C++ - если вы просто угадываете свой путь, вы, скорее всего, окажетесь с решением, которое обычно работает, но время от времени сбрасывает все ваше приложение. Выполняя что-либо с неуправляемым/родным кодом, убедитесь, что вы прекрасно понимаете, что вы делаете - неуправляемый interop просто хрупок.
В настоящее время класс Marshal
рассчитан на для неуправляемого взаимодействия. Если вы прочитали документацию для Marshal.SizeOf
, в ней конкретно указано
Возвращает размер неуправляемого типа в байтах.
И, конечно же,
Вы можете использовать этот метод, если у вас нет структуры. Макет должен быть последовательным или явным.
Возвращаемый размер является размером неуправляемого типа. Неуправляемые и управляемые размеры объекта могут отличаться. Для типов символов размер зависит от значения CharSet, применяемого к этому классу.
Если тип не может возможно быть ранжированы, что должно Marshal.SizeOf
вернуться? Это даже не имеет смысла :)
Вопрос о размере типа или экземпляра не имеет никакого смысла в управляемой среде. «Реальный размер в памяти» - это деталь реализации, насколько вам известно - это не часть контракта, и на это нельзя положиться. Если требовалось время выполнения/компилятор, он мог бы сделать каждый byte
77 байтов, и он не нарушил бы какой-либо контракт вообще, пока он точно сохраняет значения от 0 до 255 точно.
Если вы использовали struct
с явным (или последовательным) макетом, у вас будет определенный контракт на то, как будет выведен неуправляемый тип, и будет работать Marshal.SizeOf
. Однако даже тогда он будет возвращать только размер неуправляемого типа, а не управляемый, который все еще может отличаться. И снова, оба могут быть разными в разных системах (например, будет четыре байта в 32-разрядной системе и восемь байтов в 64-разрядной системе при работе в качестве 64-разрядного приложения).
Еще один важный момент заключается в том, что в приложении .NET есть несколько уровней «компиляции». Первый уровень, используя компилятор C#, является только верхушкой айсберга - и это не часть, которая обрабатывает поля переупорядочения в структурах автоматической компоновки. Он просто отмечает структуру как «авто-макет», и все сделано. Фактическая компоновка обрабатывается при запуске приложения с помощью CLI (спецификация нечетна в том, обрабатывает ли JIT-компилятор это, но я бы так и предполагал). Но это не имеет никакого отношения к Marshal.SizeOf
или даже к sizeof
- оба из них все еще обрабатываются во время выполнения. Забудьте все, что вы знаете из C++ - C# (и даже C++/CLI) - совершенно другой зверь.
Если вам нужно профилировать управляемую память, используйте профилировщик памяти (например, CLRProfiler). Но поймите, что вы все еще занимаетесь профилированием памяти в очень специфической среде - разные системы или версии .NET могут дать вам разные результаты. И на самом деле нет ничего, говоря, что два экземпляра одной и той же структуры должны быть одного размера.
«** runtime ** автоматически выбирает подходящий макет для членов объекта в неуправляемой памяти». Не компилятор. Это проблема. – Dennis
@Dennis Ну, это обрабатывается CLI, но неясно, какая часть. Я бы ожидал, что компилятор JIT - тот, кто решает. Но это не имеет большого значения - даже если это был компилятор C#, это все равно означает, что тип будет опасным и бесполезным для неуправляемого взаимодействия. – Luaan
Я согласен с тем, что не имеет смысла взаимодействовать со структурой, подобной этой. Но этот вопрос родился от другого: я просто не мог получить точный размер структуры. Я не хочу передавать его в приложение C++ или так далее, я просто удивился, что даже CLR не знает, что такое структура фактического размера. –