1字节对齐会导致内存损坏吗?

时间:2013-12-02 22:10:05

标签: c# c++ memory-mapped-files memory-layout

假设你有一个C ++中的结构(使用MFC,编译为32位),其定义如下:

#pragma pack (push, 1)
struct foo
{
   float f;
   int z;
   DWORD k;
   BYTE b;
   int i;
}; 
#pragma pack (pop,1)

现在,您在Windows中使用CreateFileMapping创建一个内存映射文件,然后将此结构的内容写入此内存区域。这是一个全局可访问的内存映射。

现在你有了C#应用程序(编译为32位)并且你创建了一个类似于这样的结构:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct foo
{
   double f;
   int z;
   int k;
   byte b;
   int i; 
}

现在当C#读取内存映射数据时,它就会被破坏。如果f的类型为double,如上所述,此特定成员的值为垃圾,其他成员的内容正确。如果将其更改为float,则所有其他成员也包含垃圾。

我的问题是,1字节对齐是否导致读取垃圾?

不幸的是,我没有在这里读取/写入内存映射的代码,但结构布局如上所述。

如果对齐不是问题,那么什么可能导致它读取垃圾?试图改变各种成员的类型几次,没有区别。

2 个答案:

答案 0 :(得分:4)

看看这两个结构,它们的不同之处在于,非托管以float开头,托管以double开头。显然这意味着结构不匹配。托管结构长4个字节,第一个之后的所有成员都偏移4个字节。

现在,你说当你有问题的代码时,第一个字段包含垃圾,但其他字段都没问题。从中可以得出唯一合理的结论是接口的写入端写入的地址与读取端读取的地址相差4个字节。

对齐和包装不是问题所在。您正在读取与用于执行写入的地址不同的4个字节的地址。

解决方案是:

  1. 确保您在共享内存中写入和读取相同位置。
  2. 将结构定义为相同。

答案 1 :(得分:1)

这听起来像是一个对齐而不是打包。 C#承诺32位代码中至少4字节对齐,以便更新32位原语是原子的。我想知道如果你为第一个成员放两个花车而不是一个双人会发生什么。