我有一个DLL项目,它提供了一个带有Delphi“变体部分”的类型定义,如下所示:
type TValue = record
case Kind : cardinal of
valueShortCard : ( ValShortCard : byte );
valueLongReal : ( ValLongReal : double );
end;
我希望这个结构的大小为12个字节(4B为基数加上8B为double,因为这是两个类型中较大的一个)。
但是,如果我有一个应用程序并为DLL中的结构调用函数sizeof(),它表示大小为16个字节。
此外,如果我直接在.exe应用程序项目中声明相同的结构,sizeof()将返回12字节的正确大小。
如果我运行应用程序并尝试从编译的DLL中获取ValLongReal值,则返回的值不正确,并且它似乎在内存中移位了4个字节。
即。如果DLL中的“double”变量显示“40 45 9a e1 47 ae 14 7b”的值(以字节值解释),则应用程序从DLL读取后返回的值为“47 ae 14 7b 77 07 06 7d“。这意味着正确数据有4字节重叠,后4个字节不正确,从内存中的后续空间读取。
注意:在Delphi XE4中已经观察到这种行为,我们刚刚升级到XE5,但它的行为方式相同。 使用的操作系统是Win7 32位。
感谢您的建议
答案 0 :(得分:3)
将其定义为:
type TValue = packed record
case Kind : cardinal of
valueShortCard : ( ValShortCard : byte );
valueLongReal : ( ValLongReal : double );
end;
此处,sizeof(TValue)=12
,正如您所料。
添加packed record
强制不生成对齐。如果没有对齐,double
将在8个字节边界上对齐,因此Kind
将使用8个字节而不是4个字节,因此valueLongReal
也会使用sizeof(TValue)=8+8=16
情况下。
请注意,在Win64下,您需要来对齐double
个变量。出于性能原因,这总是一个好主意。
另请注意,变量记录对齐方式与之前版本的Delphi XE3 AFAIR相同。