c# - 使用非对齐数组编码结构

标签 c# arrays marshalling memory-alignment

尝试编码此结构时出现异常

[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct Data
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U1)]
    [FieldOffset(0x1)]
    public byte[] a2;
}

它说 “无法从程序集‘WTF、Version=1.0.0.0、Culture=neutral、PublicKeyToken=null’加载类型‘WTF.Data’,因为它包含偏移量 1 处的对象字段,该字段未正确对齐或与非对象字段重叠”

当我将偏移量 1 更改为 0 或 4 时,一切正常。 我做错了什么?

谢谢

最佳答案

[StructLayout] 影响结构的托管和编码布局。在 .NET 中有点怪癖,但创建 blittable 结构在互操作方面是一个相当大的胜利,而且 CLR 不能忽视托管代码始终在完全非托管操作系统上运行的事实。不必创建结构的副本,而只需能够将指针传递给托管版本,这是一个非常重要的性能胜利。

您的 [FieldOffset] 值违反了 .NET 内存模型的非常强大的保证,对象引用分配始终是原子的。一个昂贵的词,意味着另一个线程永远无法观察到仅部分更新的无效对象引用。原子性需要正确对齐,在 32 位模式下为 4 的倍数,在 64 位模式下为 8 的倍数。如果它们未对齐,则处理器可能需要执行多个内存总线周期以将字节粘合在一起。这很糟糕,当另一个线程也在更新变量时,它会导致撕裂。从旧值中获取指针值的一部分,从新值中获取一部分。剩下的是使垃圾收集器崩溃的损坏指针。非常糟糕。

从 C# 的高级角度来看是晦涩难懂的东西,但是提供基本的执行保证非常重要。您无法将其与 1 对齐,只要您使用 LayoutKind.Explicit 就没有解决方法。所以不要使用它。

关于c# - 使用非对齐数组编码结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24964039/

相关文章:

c# - 枚举可以代表字符串数字吗?

c# - FileUpload 在多 View 和更新面板中不起作用

C++ 如何将整数和 float 等数据类型编码为字节串?

c# - 生成唯一标识

c# - 如何将CSS类设置为数据列表?

php - 如何合并两个数组并对重复键的值求和?

javascript - 无法访问数组元素

ios - 如何根据数组中包含的字符串隐藏特定的 UIButton

ruby-on-rails - Rspec:如何修复所需的编码格式版本 4.8; 34.92 给出的错误

c# - Pinvoke 委托(delegate) : ensuring lifetime of delegate and NullReferenceException