kag*_*san 3 c# marshalling layoutkind.explicit
我有一个结构,其中一个非重叠字段报告为重叠.
[FieldOffset(8)]
Int32 X;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
[FieldOffset(12)]
string Y;
[FieldOffset(28)]
int Z;
Run Code Online (Sandbox Code Playgroud)
报告的错误是:
无法加载类型'XXX'...它包含偏移12处的对象字段,该字段未正确对齐或由非对象字段重叠.
它仅在Release配置中发生(TRACE,DEBUG标志和不安全代码被启用,优化被关闭),猜测 - 它会发生什么?
UPD:感谢@svick.确认x64构建不是人们想要的编组.
首先,Release配置与此无关.影响它的是Platform Target:如果你将它设置为x64,你会得到这个例外,但如果你把它设置为x86,它将正常工作.
我认为这种行为的原因FieldOffset是用于指定struct托管内存中的布局(即使文档没有说明这一点),但是MarshalAs在托管内存中没有使用.
因此,托管内存中的对象包含偏移量为12的引用.由于所有引用都必须在.Net中对齐(在32位应用程序中为4个字节,在64位中为8个字节),因此会出现异常如果您将应用程序作为64位运行.
所以,问题不是你有重叠字段,而是错误信息的另一部分:字段未正确对齐.
简单的解决方法是将应用程序编译为x86.如果你不可能,我不知道如何解决这个问题.
注释@svick的正确答案,这里的问题是你的结构声明违反了CLR使该对象赋值是原子的硬承诺.这不能在64位模式下工作,偏移量为12时,对象指针可以跨越缓存行的末尾.访问这样一个未对齐的成员总是需要两次读取或写入,并且永远不会是原子的.我认为这实际上是CLR类型验证程序中的一个错误,但这不会帮助你克服这个问题.
当然,您这样做是为了与32位代码互操作,并且您正确地更改了Debug构建的Platform目标设置,但忘记了为Release构建执行此操作.这是一个per-config设置.轻松修复,只需更改Release配置的设置即可.
如果您确实需要在64位模式下工作,那么您需要将其声明为fixed char[16]相反.
| 归档时间: |
|
| 查看次数: |
1208 次 |
| 最近记录: |