Delphi XE3 x86架构下自定义record赋值异常问题咨询
问题根因
这是Delphi XE3 x86架构下的已知编译器bug,触发条件为:在记录类型的实例方法内部,将Self赋值给其他同类型记录变量,且记录大小超过12字节(即3个4字节基础字段)时:
- 记录大小≤12字节时,编译器生成逐字段拷贝的
mov指令,逻辑正常 - 记录大小>12字节时,编译器会改用
movsd块拷贝逻辑,但错误将记录第一个字段的值作为拷贝源地址,而非Self本身的内存地址。你的场景中第一个字段是FOwner,存储的是TPage实例的地址,所以实际拷贝的是TPage对象开头的内存到FSelected字段,才会出现垃圾值。
语法规范说明
你使用的FOwner.FSelected:=Self;赋值逻辑完全符合Delphi语法规范,不属于使用错误,问题完全由编译器代码生成错误导致。
可行规避方案
除了你已经在用的CopyMemory方案外,还可以选择以下更简便的处理方式:
- 显式指定地址解引用赋值,强制编译器使用正确的源地址:
FOwner.FSelected := TParagraph(Self^);
- 局部关闭该方法的编译优化,可避免编译器生成错误的块拷贝指令:
{$O-} // 关闭优化 procedure TPage.TParagraph.Select; begin FOwner.FSelected := Self; end; {$O+} // 恢复优化
- 升级编译器版本:该bug在Delphi XE7及之后的版本已经被Embarcadero官方修复,升级到更高版本可彻底解决问题。
内容的提问来源于stack exchange,提问作者loltrol
相关产品推荐
相关产品推荐

