Размер структур в.NET

Моя проблема состоит в том, чтобы отправить структуру между программой в C к программе C#.

Я сделал структуру в C#:

public struct NetPoint {
    public float lat; // 4 bytes
    public float lon; // 4 bytes
    public int alt; // 4 bytes
    public long time; // 8 bytes
}

Общий размер структуры должен составить 20 байтов.

Когда я делаю a sizeof() в C++ этой структуры,

System.Diagnostics.Debug.WriteLine(
    "SizeOf(NetPoint) = " +
    System.Runtime.InteropServices.Marshal.SizeOf(new NetPoint()));

шоу консоли отладки:

SizeOf (Сетевой узел) = 24

Но я ожидал иметь 20 байтов. Почему я вижу различие?

9
задан Peter Mortensen 15 January 2013 в 12:32
поделиться

4 ответа

Фактически, технически структура должна быть не менее из 20 байтов. Если вы выделите больше при отправке, получатель просто не будет их использовать / копировать. Проблема всегда в недостаточной доступности.

Тем не менее, я вижу проблему. Хм. Я думаю, что проблема в последнем длинном ... который ИМХО выравнивается по восьми байтам, вставляя четыре пустых байта раньше. Я думаю, что есть потеря производительности из-за того, что восьмибайтовый элемент не выровнен по восьмибайтовой границе.

Прикрепите атрибуты StructLayout для определения смещения каждого элемента вручную. Тогда вы сможете привести все в соответствие.

Ссылка: Как управлять физическим расположением полей данных в .NET Framework 2.0

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct NetPoint {  
    public float lat; // 4 bytes 
    public float lon; // 4 bytes 
    public int alt; // 4 bytes 
    public long time; // 8 bytes 
} 

Это, по крайней мере, должно выравнивать элементы по однобайтовой границе. Вы можете пойти дальше, указав точное начало каждого элемента, если это необходимо.

7
ответ дан 4 December 2019 в 11:04
поделиться

TomTom ответил на этот вопрос довольно хорошо, я думаю, но есть другая альтернатива, если вы попадаете в сложную ситуацию с структурой COM-взаимодействия. Каждое поле можно выровнять отдельно с помощью атрибутов FieldOffset.

[StructLayout(LayoutKind.Explicit)]
public struct COMPoint
{
    [FieldOffset(0)] public int X;
    [FieldOffset(4)] public int Y;
}
1
ответ дан 4 December 2019 в 11:04
поделиться

Попробуйте добавить атрибут [StructLayout(LayoutKind.Sequential, Pack = 1)] и посмотрите, что произойдет. Я подозреваю 8-байтовый паддинг, так что это будет 3x8 байт.

2
ответ дан 4 December 2019 в 11:04
поделиться

Как правило, процессорам нравится, когда переменные выравниваются в памяти по адресу, который кратен их размеру, поэтому четырехбайтовое целое число должно находиться по адресу памяти, кратному четырем, а восьмибайтовое long - по адресу, кратному восьми.

Разработчики языка C# (и C++) знают это, и они вставляют в структуры вставки для обеспечения необходимого выравнивания. Таким образом, фактическое расположение вашей структуры выглядит следующим образом:

public struct NetPoint {
    public float lat;          // 4 bytes   Offset  0
    public float lon;          // 4 bytes   Offset  4
    public int alt;            // 4 bytes   Offset  8
    int to_preserve_alignment; // 4 bytes   Offset 12
    public long time;          // 8 bytes   Offset 16
}

Вы можете исправить это, сделав long первым значением, как правило, если вы всегда помещаете самые большие значения в начало структур, у вас не будет никаких прокладок для сохранения выравнивания членов.

Вы также можете исправить это, добавив

[StructLayout(LayoutKind.Sequential, Pack = 4)]

перед объявлением структуры, но это приведет к неправильному выравниванию long time, что снижает производительность. На некоторых процессорах это сильно снижает производительность (например, ALPHA AXP будет сбоить при неправильно выровненных членах). На процессорах x86 снижение производительности незначительно, но есть опасность, что на будущих процессорах снижение производительности будет значительным, поэтому лучше разрабатывать структуры для правильного выравнивания (а не упаковывать их), если это возможно.

9
ответ дан 4 December 2019 в 11:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: