【问题标题】:Marshal.Sizeof() returning unexpected valueMarshal.Sizeof() 返回意外值
【发布时间】:2020-12-08 01:29:27
【问题描述】:

我正在调试由第 3 方编写的 C# 代码。该项目是一个旧的 C++ 项目,由承包商用 C# 重写,我无权访问承包商。我编写了原始的 C++ 版本。

问题在于,当 C# 代码获取表示通过 UDP 连接接收的数据的结构的大小时。

结构体定义为:

[StructLayout(LayoutKind.Sequential,Pack=1)]
internal class PROXY_HDR {
    public ushort pad;
    public ushort label;
    public char flags;
    public ushort length;
    public char[] ip = new char[4];
    public ushort port;
}

这个结构的大小被检索为:

int size = Marshal.Sizeof(typeof(PROXY_HDR));

并且返回的值是 17 而不是预期的 13。有 4 个字节的差异,我怀疑 ip 成员,但这只是因为它的表达方式与其他成员不同(使用 'new' ),但我没有其他决定依据。

我通常不会在我的 C# 代码中使用这种类型的封送处理来毫无问题地解析接收到的数据包,所以我不知道如何修改这个结构定义以使其与原始版本大小“对齐”-明智的。

我可以用

替换元帅线
int size = 13;

但那是作弊,对吧?

我可以通过某种方式修改此布局以使尺寸正确吗?

【问题讨论】:

  • 我没有实际答案,但您可以尝试像我在 this answer 中针对不相关问题所做的那样明确设置字段偏移量。
  • 你为什么希望它是 13?
  • @IanKemp 因为对于 x86(32 位)它确实返回 13,如果编译 x64 则返回 +4...
  • @AlexeiLevenkov -- 如果你正确编组它,它会在 64 位 32 位 下返回 13 个字节
  • @Andy 确实 - 也没有问题要问:) 显然,每天不做这些事情的人都不会期望 char 有 sizeof = 1 ... 而 OP 不知道引用类型...有很多东西要解释。

标签: c# c++ marshalling structlayout


【解决方案1】:

将此添加到结构中:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal class PROXY_HDR
{
    public ushort pad;
    public ushort label;
    public byte flags;
    public ushort length;
    [MarshalAs(UnmanagedType.ByValArray,
        SizeConst = 4, ArraySubType = UnmanagedType.U1)]
    public byte[] ip;
    public ushort port;
}

这将告诉编译器将其视为典型的 C 样式数组,而不是指针。这应该是字节,因为 IP 地址是一个无符号字符数组。 char 通常不用于这些类型的标头中,通常是 byte(即:unsigned char

【讨论】:

  • @Bathsheba -- 我认为是对的。我的解释表明我不是100%确定为什么是对的。我将不得不对此进行研究并提出更好的解释。
  • @Andy:是的,这行得通。至于 'char' 的定义,我认为 C# 开发人员试图尽可能忠实于原始 C++ 代码,并且这个特定的结构从未像大多数其他结构一样更新为使用 'byte'。谢谢!!
  • 请注意,最初的问题只是由于将 ip 视为指针(32 位或 64 位,取决于您编译代码的方式)。显然char 是默认编组的单字节 - 我没有要确认的链接,但您可以轻松尝试自己(并直接查看大小 = 13 或 17,只能通过 char = 1 的大小来解释)。
  • @user3235770 -- 请注意,您可以通过在属性中添加ArraySubType = UnmanagedType.U1 或其他任何内容来使其更具体。我不知道这是否会有所帮助。
  • 实际上我只是注意到我只添加了 MarshalAs 行,而不是在后面的行中从 CHAR 更改为 BYTE。很明显,这是作为指针的解释。
猜你喜欢
  • 2020-06-24
  • 1970-01-01
  • 1970-01-01
  • 2013-06-26
  • 2014-12-11
  • 2016-01-30
  • 1970-01-01
  • 2019-04-26
  • 1970-01-01
相关资源
最近更新 更多