Delphi 64位:如何找到错误的类型转换?

15

我正在将一个大型的Delphi代码库适配成64位。在许多情况下,有一些行会将指针转换为/从32位值,类似于这种情况:

var
  p1,p2 : pointer;
begin
  inc(Integer(p1),10);
  p2 := Pointer(Integer(p1) + 42);

我用NativeInt-casts代替了这些casts以使它们在64位模式下正确,但我不确定是否找出了所有casts。有时候casts更加微妙,所以仅仅搜索“integer(”字符串也不足够。

由于如果指针值超出整数类型的范围,“integer(”casts将在64位失败,我有一个想法:如果我可以强制内存管理器分配超过4gb的内存(因此指针值使用超过32位),那么我就会得到运行时错误并更容易地找到错误的casts。这可能吗?或者有人可以推荐其他技术吗?

1个回答

21

除了使用您正在使用的文本搜索之外,没有找到这些转换的魔术技巧。如果编译器能够警告这样的转换就太好了。我发现它没有这样做非常令人失望。

当您发现此类问题时,请不要更改为 NativeInt。将指针更改为类型化指针,并使用指针算术运算。

var
  p1, p2: PByte;
....
inc(p1, 10);
p2 := p2;
inc(p2, 42);

那么你的代码将永远是安全的。

仍然有一些情况需要强制转换为整数。例如,当传递地址给 SendMessage 时。但应根据需要将其转换为 WPARAMLPARAM

你强制运行时错误的想法很好,而且幸运的是,这并不是原创的!你应该使用完整版本的 FastMM 并定义 AlwaysAllocateTopDown。这会强制 FastMM 调用 VirtualAlloc 时传递 MEM_TOP_DOWN 标志。这将使大多数错误的转换成为运行时指针截断错误。

然而,这只会强制在您的内存管理器分配的内存中进行自上而下的分配。进程中的其他模块将使用默认的自下而上策略。您可以设置一个机器范围的设置来更改该默认策略。将 HKLM\System\CurrentControlSet\Control\Session Manager\Memory Management\AllocationPreference 设置为 REG_DWORD,值为 0x100000,然后重新启动。

请注意,这可能会导致您的计算机稳定性问题。许多应用程序无法处理此类设置。特别是很少有反病毒产品能够处理此类设置。MSE是我发现能够在全局自上而下分配中正常工作的产品。此外,64位调试器无法在自上而下分配模式下运行!因此,您必须在没有调试器的情况下进行此类测试。即使在XE3中,我的QC报告仍然未解决此问题。

2
谢谢,MEM_TOP_DOWN 标志非常有趣。我正在处理的项目有一个自定义的调试分配器,所以现在我已经修改了使用该标志。虽然很慢,但我已经找到了一些转换错误。 - Ville Krumlinde

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接