4

假设您在 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# 读取内存映射数据时,它显示为已损坏。如果类型fdouble,如上所述,则该特定成员的值是垃圾,其他成员具有正确的内容。如果将其更改为float,则所有其他成员也包含垃圾。

我的问题,可能是 1 字节对齐导致了垃圾的读取吗?

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

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

4

2 回答 2

4

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

现在,你说当你有问题的代码时,第一个字段包含垃圾,但其他字段很好。从中唯一合理的结论是,接口的写入端正在写入与读取端正在读取的地址偏移 4 个字节的地址。

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

解决方案是:

  1. 确保您在共享内存中的同一位置写入和读取。
  2. 将您的结构定义为相同。
于 2013-12-02T22:20:03.647 回答
1

这听起来像是对齐而不是打包。C# 承诺在 32 位代码中至少有 4 字节对齐,因此更新 32 位原语是原子的。我想知道如果您为第一个成员放置两个浮点数而不是双精度数会发生什么。

于 2013-12-02T22:22:17.517 回答