为什么在SafeBuffer.WriteArray <t>和SafeBuffer.ReadArray <t>中使用Marshal.AlignedSizeOfStruct <t>而不是Marshal.SizeOfStruct <t>?</t> </t> </t> </t>

时间:2014-09-04 07:28:59

标签: c# .net clr unmanaged

根据http://referencesource.microsoft.com/#mscorlib/system/runtime/interopservices/safebuffer.cs

SafeBuffer使用结构类型的对齐大小而不是结构类型的实际大小。当写入需要成为密集的结构数组的内容以及从缓冲区中预先存在的密集包装的非对齐结构数组中读取时,这似乎会导致对齐问题。在第一种情况下,使用对齐而不是实际大小会导致不需要的填充字节。在第二个,数据被破坏。我有两个问题(4个问题,但3个是相关的):

  1. 除了使用对SafeBuffer.Write<T> / Read<T>的顺序调用(速度较慢)手动对齐访问权限,或放弃SafeBuffer类(因此相当不错)之外,还有其他解决方法吗?完全UnmanagedMemoryAccessor课程?
  2. 这种选择背后的原因是什么?为什么CLR在非托管内存上强制执行它自己的对齐要求?为什么这不应被视为错误?

1 个答案:

答案 0 :(得分:1)

Hmya,这些问题的答案总是主观的,我们没有让.NET Framework设计师在这里做出贡献,将他们的设计会议笔记传递给我们。但你可以放心地认为这是而不是一个bug,而且这很痛苦。当然至少有一个原因是,在.NET中支持MMF这么长时间。

每个人都喜欢忽略或希望远离结构包装和对齐细节。 CLR在隐藏它们方面做得非常好。但是降压在这里停止,再也无法忽视它们了。冷酷的事实是,让每个人都快乐是完全不可能的。该框架没有合理的方法来猜测MMF另一端的代码是什么样的。这是不可知的,MMF完全过于简单化,不支持像元数据这样的东西。有一种明确的故障模式,一端是32位进程,另一端是64位进程。他们使用不同的对齐选择,4 vs 8.更多,特别是如果它是另一端的本机代码使用自己的#pragma pack。

鉴于框架永远不能100%正确,他们选择至少使.NET代码在任何一方运行时都正确有效。一个完全合理的选择。

唯一真正的缺陷是文档缺乏。当您需要与本机代码互操作时, 会头疼。目前,试验和错误是唯一的好办法。或者问一个关于你当然遇到的特定问题的问题:)