【问题标题】:incorrect members order in a C# structureC# 结构中的成员顺序不正确
【发布时间】:2010-10-16 00:42:17
【问题描述】:

我有一个 TCP 客户端,它将一个数据包放入一个结构中

using System.Runtime.InteropServices;

[StructLayoutAttribute(LayoutKind.Sequential)]
public struct tPacket_5000_E
{
    public Int16 size;
    public Int16 opcode;
    public byte securityCount;
    public byte securityCRC;
    public byte flag;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.I1)]
    public byte[] blowfish;
    public UInt32 seedCount;
    public UInt32 seedCRC;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.I1)]
    public UInt32[] seedsecurity;
}

我用来将数据包放入结构中的代码是:

tPacket_5000_E packet = new tPacket_5000_E();
GCHandle pin = GCHandle.Alloc(data, GCHandleType.Pinned);
packet = (tPacket_5000_E)Marshal.PtrToStructure(pin.AddrOfPinnedObject(), typeof(tPacket_5000_E));
pin.Free();

现在,在我继续之前,我必须告诉你,我正在将这个项目从 C++ 翻译成 C#。

这就是问题所在:

tPacket_5000_E 的最后 3 个成员是 Int32(我也试过 UInt32),在 C++ 中是 DWORD。 这三个成员之前的值,即NOT Int32,与C++中的值相同。(我在C++和C#项目中都注入了相同的数据包)。

但是,这三个成员的值不同。

在 C++ 中,这些值是(正确):

  1. seedCount:0x00000079
  2. seedCRC:0x000000d1
  3. SeedSecurity:
  4. -[0]:0x548ac099
  5. -1:0x03c4d378
  6. -[2]:0x292e9eab
  7. -[3]:0x4eee5ee3
  8. -[4]:0x1071206e

在 C# 中,这些值是(不正确):

  1. seedCount:0xd1000000
  2. seedCRC:0x99000000
  3. SeedSecurity:
  4. -[0]: 0x78548ac0
  5. -1:0xab03c4d3
  6. -[2]: 0xe3292e9e
  7. -[3]: 0x6e4eee5e
  8. -[4]: 0x00107120

两个应用程序中的数据包是相等的

byte[] data = new byte[] {
0x25, 0x00, 0x00, 0x50, 0x00, 0x00, 0x0E, 0x10, 
0xCE, 0xEF, 0x47, 0xDA, 0xC3, 0xFE, 0xFF, 0x79, 
0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, 0x99, 
0xC0, 0x8A, 0x54, 0x78, 0xD3, 0xC4, 0x03, 0xAB, 
0x9E, 0x2E, 0x29, 0xE3, 0x5E, 0xEE, 0x4E, 0x6E, 
0x20, 0x71, 0x10};

Click here for further information

为什么结构中的最后三个成员不同以及如何修复它们?

提前致谢!

【问题讨论】:

    标签: c# struct memory-layout


    【解决方案1】:

    我希望你的问题的根源是三个字节值

    public byte securityCount;
    public byte securityCRC;
    public byte flag;
    

    导致接下来的 32 位值不是字对齐的,并且您的两组代码添加(或不添加)内部填充的方式不同。

    我希望不同的包装看起来像这样:

    C++ C# ==================================================== =============== [大小][操作码] [大小][操作码] [secCnt][secCrc][标志][blow0] [secCnt][secCrc][标志][blow0] [吹1][吹2][吹3][吹4][吹1][吹2][吹3][吹4] [blow5][blow6][blow7][seedCou [blow5][blow6][blow7]..PAD... nt ][seedCRC [seedCount ] ][seedSec [种子CRC] urity0 ][seedSec [seedSecurity0] urity1 ][seedSec [seedSecurity1] urity2 ][seedSec [seedSecurity2 ] urity3 ][seedSec [seedSecurity3 ] urity4 ] [seedSecurity4 ]

    ... 使用 C# 插入一个字节的填充,这会导致后面的值减少一个字节。

    你可以试试

    [StructLayout(LayoutKind.Sequential,Pack=1)]
    

    在你的结构定义之前,它应该使用尽可能少的空间。

    Mastering Structs in C# 提供了一些关于如何/为什么发生这种情况的好信息。

    【讨论】:

    • @Daniel L,您能否提出解决此问题的解决方案?
    【解决方案2】:

    我怀疑Daniel L 的回答是正确的。

    我会尝试在标志之后添加第 4 个字节。我的猜测是您的 C++ 编译器正在对齐字边界上的值。这也会“对齐”C# 版本。

    【讨论】:

    • 我刚刚在标志下添加了一个新字节(不需要公共字节;)结果:应该放在blowfish[0](下一个成员)的值被移动到我添加的值并且最后三个值仍然相同。
    • Reed Copsey,你的解决方案没有用,但我非常感谢你的帮助,所以我也挖掘了你的答案!我想通了,感谢 Daniel L。感谢大家的快速支持。
    猜你喜欢
    • 2013-02-24
    • 2015-01-05
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 2020-01-05
    • 2017-06-11
    • 1970-01-01
    相关资源
    最近更新 更多