【问题标题】:Delphi code fails at 64 bits access violationDelphi 代码因 64 位访问冲突而失败
【发布时间】:2018-09-21 12:58:04
【问题描述】:

此 Delphi 代码在编译为 32 位时有效,但在编译为 64 位时会出现访问冲突。是代码有问题,还是编译器有问题?

{$APPTYPE CONSOLE}

uses
  SysUtils;

const
  MaxSize = 2; // nothing special about this value, could equally be 1

type
  TArraySize = 1..MaxSize;

procedure Main;
var
  size: TArraySize;
  arr: array [-MaxSize..MaxSize] of Integer;
begin
  FillChar(arr, SizeOf(arr), 0); // zero initialize
  size := MaxSize;
  Writeln(arr[-size]);
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

【问题讨论】:

  • 当 Kernel.Size = beMaxGaussKernelSize 时,它​​会在开始时准确地给出 AV
  • 我觉得这段代码就够了
  • 创建minimal reproducible example 很容易,这样我们就不需要拼凑起来了。想象一下,如果我们可以将一个完整的程序粘贴到我们的编辑器中?这不需要我们付出任何努力。
  • 当然。但是为什么要让别人做那些额外的工作。我把你的 sn-ps 变成了minimal reproducible example。这对回答的人来说意义重大。
  • 请注意,我现在进一步简化了代码。这是一项非常重要的学习技能。通过这样做,您可以缩小关注问题的任何人的关注范围。尤其是你自己。如果您自己完成此操作并最终得到这样的代码,它会将您带到编译器有缺陷的特定点。

标签: delphi


【解决方案1】:

这是一个编译器错误。编译器不处理

arr[-size]

正确,大概是因为size 是一个子范围类型。

您可以通过强制编译器在 Integer 上下文中执行算术来解决该错误。

arr[-Integer(size)]

您应该向 Embarcadero 的质量门户提交错误报告。

更新

我在 XE7 中对此进行了测试。根据评论,该缺陷似乎至少在西雅图已得到修复。

【讨论】:

  • 谢谢,就是这样!...但我的眼睛完全无法察觉。我不得不说这不是我的代码,否则我会以不同的方式编码它
  • 您的 mcve 在西雅图运行良好,32 位和 64 位。你在哪个版本中测试过这个?
  • @J... 我用 XE7 测试了这个
  • 那么可能不需要 QP,因为它至少在 D10 中似乎已修复。
  • FWIW,错误似乎是 64 位代码将 RAX 设置为 2,然后否定 EAX,这使得 RAX 为 $00000000FFFFFFFE,而不是 $FFFFFFFFFFFFFFFE。然后它访问 [RBP+4*RAX+$2C]。 RAX 不是-2,所以这是非常错误的。后来的版本插入了一个MOVSXD RAX,EAX,这个符号把EAX扩展成RAX,所以变成-2。
【解决方案2】:

产生访问冲突错误的编译器总是有错误。编译器不应该这样做,而是优雅地处理每个发生的错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    • 2021-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多