c# - Com 互操作结构定义与内存布局不匹配

标签 c# c++ com interop

在 COM header (vds.h) 中定义了一个结构:

typedef struct _VDS_DISK_EXTENT
{
    // A Guid
    VDS_OBJECT_ID diskId;
    // An Enum, with the largest defined value 0x7FFF
    VDS_DISK_EXTENT_TYPE type;
    ULONGLONG ullOffset;
    ULONGLONG ullSize;
    // Guid
    VDS_OBJECT_ID volumeId;
    //Guid
    VDS_OBJECT_ID plexId;
    ULONG memberIdx;
} VDS_DISK_EXTENT;

我已经注释了一些字段的类型。根据此 header 定义,该结构似乎有 72 个字节大。但是,当我在 C# 中编码它时(我得到一个 IntPtr 到这些结构的数组)并查看 IntPtr 指示的内存,我看到了这个:

0x01717A50  a8 c5 af 28 37 e1 0d 43  -> diskId
0x01717A58  b0 87 e2 ef 94 5f 9f 27  -> diskId
0x01717A60  02 00 00 00 00 00 00 00  -> first 4 bytes are extent type, second 4?
0x01717A68  00 00 70 23 00 00 00 00  -> offset
0x01717A70  00 00 50 4d 74 00 00 00  -> size
0x01717A78  38 3c 22 26 e9 de df 44  -> volumeId
0x01717A80  81 f3 ba ee af e2 ad 2b  -> volumeId
0x01717A88  48 98 78 bb 7f dd bc 41  -> plexId
0x01717A90  94 17 db d2 86 01 54 ce  -> plexId
0x01717A98  00 00 00 00 00 00 00 00  -> first 4 bytes are membderIdx, second 4?

如您所见,有 2 个 4 字节的区域未计算在内。 c++ 枚举声明为 typedef enum _VDS_DISK_EXTENT_TYPE { 所以我认为它不是 8 个字节。与 memberIdx 相同,它被声明为一个 ULONG,所以它是 4 个字节。这个填充在哪里定义或者每个字段的偏移量在哪里定义?如果我必须查看内存中的每个对象并弄清楚字段之间的真正边界在哪里,那么使用此 com 程序集中的对象几乎是不可能的。

最佳答案

这看起来像是结构成员对齐的情况。具体来说,这个结构是用 8 字节的对齐方式编译的,这是 Visual C++ 的默认值。请注意,每个成员都以 8 字节为边界开始。如果存在小于 8 字节的连续成员(例如,两个连续的 ULONG),您将不会在第一个 ULONG 上看到额外的填充(因为 4 -byte 成员可以在使用对齐值 >= 4) 时在 4 字节边界上对齐。但是因为你有一个 ULONG 后跟一个 ULONGLONG,所以 ULONG 成员被填充以便下面的 ULONGLONG 成员在 8 字节边界上对齐(因为 8 字节成员不能在 4 字节边界上对齐)。

https://msdn.microsoft.com/en-us/library/xh3e3fd0.aspx

关于c# - Com 互操作结构定义与内存布局不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45018016/

相关文章:

c# - 选中时如何更改 System.Windows.Forms.ToolStripButton 突出显示/背景颜色?

c# - 创建新的 .NET 6 MAUI 项目

c++ - 在Qt中获取毫秒精度的当前时间

com - 在 Vista 上取消注册类型库

c# - 从 Javascript 调用 C# BHO 方法

c# - HTML敏捷包: How to check if an element is visible?

c# - .Net 处理非托管内存的方式是否不同于 C++ 运行时/二进制可执行文件?

c++ - 递归 C++ 函数中 if 与 while 的行为

c++ - 显示对已定义对象的 undefined reference

c++ - 如何加载 DLL 作为本地服务器