2013-03-19 4 views
5

Предоставляет ли .NET какие-либо гарантии того, что массивы байтов .NET всегда правильно выровнены? Мне это нужно для лечения, например. массив байтов в небезопасном контексте как longs в x64 для изменения кусков данных с собственным размером регистра.Являются ли массивы в .NET естественным путем?

Но до сих пор я не нашел документов, которые CLR дает мне какие-либо гарантии того, что доступ к памяти будет правильно выровнен.

+1

Это может помочь: http://stackoverflow.com/questions/9741395/alignment-of-arrays-in-net –

+0

В принятом ответе не рассматривается исходный вопрос о том, как массивы выровнены. –

+1

Как могут быть смещены байтовые массивы? –

ответ

6

Нет. И на самом деле массивы могут быть неправильно выровнены для джиттера x86. В частности, проблема с double [] и long [], сборщик мусора обеспечивает гарантию того, что они будут выровнены по 4. Что объясняет специальное правило для double [], такой массив будет выделен в кучке больших объектов, когда он имеет 1000 или более элементов. Значительно меньше обычного правила для распределений LOH, 85000 и более байтов. LOH зависит от гарантии выравнивания кучи Windows, выровненной на 8. Это не проблема в джиттере x64.

Получение более конкретной информации по вашему вопросу: массивы байтов никогда не могут быть проблемой. Байт всегда выровнен, независимо от того, где начинается массив. «Длинные» в неуправляемом коде, скомпилированном с компилятором Microsoft, тоже не проблема, это 4 байта, поэтому он всегда удачно выравнивается с правилами выравнивания GC по умолчанию. Он по-прежнему 4 байта в режиме x64, поэтому проблем нет.

+0

Я хочу обработать массив байтов как массив, как longs, который нуждается в правильном выравнивании. Байт-массив - это только транспортный носитель, как он читается .NET. Правильно ли правило выравнивания по 4 байтам на x64? В любом случае я не могу предположить естественное выравнивание для массивов байтов, которые интерпретируются как разные данные, такие как longs или floats? –

+0

Нет, как указано, это не проблема в x64. Все выравнивается до 8, как требуется для ссылок на объекты, которые имеют 8 байтов в 64-битном коде. –

+2

Спасибо за подробный ответ. Я всегда удивляюсь, как вы знаете такие вещи, не имея полного кода clr в своем уме. –

0

В объектах .NET (из которых массивы являются видами) всегда выровнены на основе размера указателя (например, 4 байта или 8 байт). Таким образом, указатели объектов и массивы объектов всегда выравниваются в .NET.

Следует также отметить, что разыменование указателя в .NET не требует выравнивания. Однако это будет медленнее. например если у вас есть действительный байт * указатель и что указывает на данные, которые по меньшей мере восемь байт в длину, вы можете бросить его на долгое время * и получить значение:

unsafe 
{ 
    var data = new byte[ 16 ]; 
    fixed (byte* dataP = data) 
    { 
     var misalignedlongP = (long*) (dataP + 3); 
     long value = *misalignedlongP; 
    } 
} 

Чтение через исходный код .NET, вы можете что Microsoft иногда учитывает выравнивание и часто этого не делает. Примером может служить внутренний метод System.Buffer.Memmove (см. https://referencesource.microsoft.com/#mscorlib/system/buffer.cs,c2ca91c0d34a8f86). Этот метод имеет пути к кодам, которые заставляют байты * длиться без каких-либо проверок выравнивания в нескольких местах, а вызывающие методы также не проверяют выравнивание.

Смежные вопросы