c# – 使用非对齐数组的编组结构

我试图编组这个结构时遇到异常

[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#的高级角度来看,模糊的东西,提供基本的执行保证是非常重要的.只要使用LayoutKind.Explicit,就不能将它错位为1,没有解决方法.所以不要使用它.

相关文章

目录简介使用JS互操作使用ClipLazor库创建项目使用方法简单测...
目录简介快速入门安装 NuGet 包实体类User数据库类DbFactory...
本文实现一个简单的配置类,原理比较简单,适用于一些小型项...
C#中Description特性主要用于枚举和属性,方法比较简单,记录...
[TOC] # 原理简介 本文参考[C#/WPF/WinForm/程序实现软件开机...
目录简介获取 HTML 文档解析 HTML 文档测试补充:使用 CSS 选...