You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi 11.2出现Integer overflow error,10.4.2无此问题的原因及解决

问题原因与解决方案

原因分析

  1. 溢出检查默认行为变更:Delphi 11.2默认开启了整数溢出检查({$OVERFLOWCHECKS ON}),而Delphi 10.4.2及更早版本默认关闭该检查。你的代码中NPointer^ * I的计算会产生超过32位无符号整数(Cardinal)范围的值,旧版本编译器会直接截断溢出部分,新版本则严格触发溢出错误。
  2. 类型计算的隐式溢出:NPointer^是32位无符号类型,I是8位无符号类型,两者相乘的最大可能值($FFFFFFFF * 255)远超过32位无符号数的上限,必然触发溢出。

解决方案

方案1:临时禁用溢出检查(最快适配旧逻辑)

在触发溢出的代码段前后添加编译器指令,临时关闭溢出检查,和旧版本行为保持一致:

procedure TForm.SetModulo(A: TCode128);
var
  I, J, Remainder : Byte;    
  NPointerStart: PCardinal;
  NPointer: PCardinal;
  ModuloPointer: PCardinal;
  WordPointer: PWord;
begin
  NPointerStart:= Addr(A);
  for I:= 0 to 255 do begin
    NPointer:= Pointer(NPointerStart);
    Remainder:= 0;
    ModuloPointer:= Addr(Modulo[I][0]);
    for J:= 0 to 3 do begin
      {$OVERFLOWCHECKS OFF} // 临时关闭溢出检查
      ModuloPointer^:= ((NPointer^ * I) + Remainder);
      {$OVERFLOWCHECKS ON} // 恢复溢出检查

      {$OVERFLOWCHECKS OFF}
      WordPointer:= Pointer(NPointer);
      Remainder:= ((WordPointer^ * I) + Remainder) div $10000;             
      Inc(WordPointer);
      Remainder:= ((WordPointer^ * I) + Remainder) div $10000;              
      {$OVERFLOWCHECKS ON}

      Inc(NPointer);
      Inc(ModuloPointer);
    end;
    ModuloPointer^:= Remainder;
  end;
end;

方案2:使用64位类型承载计算(更安全的写法)

通过将计算过程转换为64位整数(Int64),避免溢出,再转换回目标类型,既兼容旧逻辑又符合新版本的安全要求:

procedure TForm.SetModulo(A: TCode128);
var
  I, J, Remainder : Byte;    
  NPointerStart: PCardinal;
  NPointer: PCardinal;
  ModuloPointer: PCardinal;
  WordPointer: PWord;
  Temp: Int64; // 用64位变量承载计算,避免溢出
begin
  NPointerStart:= Addr(A);
  for I:= 0 to 255 do begin
    NPointer:= Pointer(NPointerStart);
    Remainder:= 0;
    ModuloPointer:= Addr(Modulo[I][0]);
    for J:= 0 to 3 do begin
      // 用Int64计算,避免溢出
      Temp := Int64(NPointer^) * I + Remainder;
      ModuloPointer^:= Cardinal(Temp); // 截断回32位,和旧逻辑一致

      WordPointer:= Pointer(NPointer);
      Temp := Int64(WordPointer^) * I + Remainder;
      Remainder:= Byte(Temp div $10000);             
      Inc(WordPointer);
      Temp := Int64(WordPointer^) * I + Remainder;
      Remainder:= Byte(Temp div $10000);              

      Inc(NPointer);
      Inc(ModuloPointer);
    end;
    ModuloPointer^:= Remainder;
  end;
end;

额外说明

你之前尝试强制转换指针为Uint64没解决问题,是因为你需要转换的是指针指向的值,而非指针本身的地址。另外,你用PCardinal指向Byte数组的写法是合理的,每次赋值会连续写入4个Byte,刚好匹配Modulo[I][0]到Modulo[I][3]的存储范围。

内容的提问来源于stack exchange,提问作者fuzzhead

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 21:50:36