Com Interop结构定义与内存布局不匹配

时间:2017-07-10 17:13:54

标签: c# c++ com interop

在COM标头(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;

我注释了一些字段的类型。根据此标头定义,结构看起来大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程序集中的对象。

1 个答案:

答案 0 :(得分:1)

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

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