6

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

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

4

2 回答 2

8

不会。事实上,阵列可能会因 x86 抖动而错位。特别是 double[] 和 long[] 的问题,垃圾收集器只提供保证它们将在 4 对齐。这就解释了 double[] 的特殊规则,这样的数组将在大对象堆中分配有 1000 个或更多元素。大大少于 LOH 分配的正常规则,85000 或更多字节。LOH 取决于 Windows 堆对齐保证,对齐为 8。否则这在 x64 抖动中不是问题。

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

于 2013-03-19T14:42:10.483 回答
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)。该方法具有将 byte* 转换为 long 的代码路径,而在某些地方没有任何对齐检查,并且调用方法也不检查对齐方式。

于 2017-11-06T15:31:10.513 回答