.NET中的数组是否自然对齐?

时间:2013-03-19 14:08:25

标签: .net clr

.NET是否保证.NET字节数组始终正确对齐?我需要这个来治疗,例如不安全上下文中的字节数组,在x64中为long,用于修改具有本机寄存器大小的数据块。

但到目前为止,我还没有找到任何文档,CLR确实给了我任何保证,我的内存访问然后正确对齐。

2 个答案:

答案 0 :(得分:7)

没有。事实上,对于x86抖动,数组可能会出现错误对齐。特别是double []和long []的问题,垃圾收集器只提供了它们将在4对齐的保证。这解释了double []的特殊规则,这样的数组将在大对象堆中分配时有1000个或更多元素。远低于LOH分配的正常规则,85000或更多字节。 LOH依赖于Windows堆对齐保证,对齐为8.这在x64抖动中不是问题。

更具体地解决您的问题:字节数组永远不会成为问题。无论数组从何处开始,一个字节始终是对齐的。使用Microsoft编译器编译的非托管代码中的“long”也不是问题,它是4个字节,因此始终与默认的GC对齐规则愉快地对齐。它在x64模式下仍然是4个字节,所以也没有问题。

答案 1 :(得分:1)

在.NET对象中(其数组是一个种类)总是根据指针大小对齐(例如,4字节或8字节对齐)。因此,对象指针和对象数组始终在.NET中对齐。

我还应该指出,在.NET中取消引用指针并不需要对齐。但是,它会慢一些。例如如果你有一个有效的byte *指针并指向长度至少为8个字节的数据,你可以将它转换为long *并得到值:

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)。该方法具有将字节*转换为long的代码路径,而在几个地方没有任何对齐检查,并且调用方法也不检查对齐。