StructLayout 和 FieldOffset 的未定义行为

Posted

技术标签:

【中文标题】StructLayout 和 FieldOffset 的未定义行为【英文标题】:undefined behaviour with StructLayout and FieldOffset 【发布时间】:2018-01-04 22:13:19 【问题描述】:

我已使用 PtrToStructure 函数(在 VB.NET 中)从有效指针中成功提取结构对象,但某些对象成员的结果不正确(与 C++ 示例相比):

代码是:

StructLayout(LayoutKind.Explicit, pack:=1, CharSet:=CharSet.Ansi)> _
    Public Structure MyStruct

        <FieldOffset(0)> _
        Dim Width As UInt32 ' 350 correct
        <FieldOffset(4)> _
        Dim Height As UInt32 ' 466 correct
        <FieldOffset(20)> _
        Dim Buffer As IntPtr ' variable but correct
        <FieldOffset(24)> _
        Dim BufferPitch As Integer ' 1408 correct
        <FieldOffset(16)> _
        Dim SurfaceType As Integer ' -2147483645 correct
        <FieldOffset(unknow)> _
        Dim WindowWidth As UInt32 ' must be 356, tested from 0 to 230
        <FieldOffset(unknow)> _
        Dim WindowHeight As UInt32 ' must be 495, tested from 0 to 100
        <FieldOffset(15)> _
        Dim ScreenHeight As UInt32 ' 768 correct
        <FieldOffset(36)> _
        Dim ScreenWidth As UInt32 ' 1366 correct
        <FieldOffset(44)> _
        Dim ScreenDepth As UInt32 ' 32 correct
End Structure

我找不到 WindowWidth 和 WindowHeight 的 FieldOffset 参数的确切值。问题是为什么以及如何解决它们?

struct myStruct 
 
    U32 Width; // U32 = 32-bit unsigned integer 
    U32 Height; 
    VOID_PTR Buffer;
    S32 BufferPitch; // 32-bit signed integer 
    COPY_FLAGS SurfaceType; // integer 
    U32 WindowWidth; 
    U32 WindowHeight; 
    U32 ScreenWidth; 
    U32 ScreenHeight; 
    U32 ScreenDepth; 

【问题讨论】:

ScreenHeight 上 15 的偏移量几乎肯定是错误的;偏移量应该是 4 或 8 的倍数。ScreenWidth 和 ScreenDepth 上 36 和 44 的偏移量是可疑的,因为从 24 到 36 以及从 36 到 44 的间隙比它们之前的数据大得多。偏移量应该是 8,偏移量是 12。 15 的偏移量给出了正确的结果(我使用另一个指针进行了测试和重新测试,因此使用其他结构)。与其他成员相同,问题在于 WindowWidth 和 WindowHeight 成员。 C++ 结构是否按照声明的方式完全显示?您确定 C++ 端没有其他东西会影响结构布局吗?编译器选项,编译指示?我能想到的获得 15 偏移量的唯一方法是拥有单字节大小的东西,并且告诉 C++ 不要对齐结构。 唯一的可变长度是 IntPtr;它将是 4 或 8 字节长(x86 或 x64)。根据您显示的内容,所有内容都应在 4 字节边界内。 好的,文档显示了上面的结构,但是当我在 C++ 示例中编写“->”符号时,它显示了一个很大的成员列表,所以要小心。 【参考方案1】:

这个问题解决了。通过更改位于 8 和 12 中的偏移量并将指针参数修改为另一个值。

【讨论】:

以上是关于StructLayout 和 FieldOffset 的未定义行为的主要内容,如果未能解决你的问题,请参考以下文章

C# StructLayout.Explicit 问题

C# pack 1 StructLayout 网络

c# 中的联合与 StructLayout

使 StructLayout 在类上工作,因为它在结构上工作

在使用联合调用 PInvoke 结构时,我在使用 StructLayout( LayoutKind.Explicit ) 时做错了啥?

为啥这个用于 C++ 的 .NET StructLayout 示例