64 位 PChar 指针算术给出范围检查错误

问题描述 投票:0回答:1

我正在追踪第 3 方代码深处的错误,其中声明

 fStringLen := Str - fToIdent;

给出运行时错误,其中:

  • Str
    是PChar私有函数参数,此时为''
    (最初不为空,但 Inc(Str) 执行到循环结束)
  • fStringlen 是一个整数私有属性,值为 0
  • fToIdent 是 PChar 私有属性,它在检查器窗口中显示
    nil {%0}

enter image description here

目前还不清楚是否有任何事情追踪所有事件,看起来好像没有对

fToIndent
PChar 属性 (它没有可以在其上放置断点的 setter),或者如果 并且这只是创建其对象后的初始状态。

我们的软件有一个较旧的 32 位版本和较旧版本的 3rd 方软件,但该代码段是相同的。如果我运行代码,这些值是相同的,但不会出现范围检查错误。

FWIW,这是代码,请参阅最后一条语句:

    function TdaSynHighlighterSQL.HashKey(Str: PChar): Integer;
    // called with Str = 'absolute'

      function GetOrd: Integer;
      begin
        case Str^ of
          '_': Result := 1;
          'a'..'z': Result := 2 + Ord(Str^) - Ord('a');
          'A'..'Z': Result := 2 + Ord(Str^) - Ord('A');
          '@':
            if fDialect in [sqlMSSQL7, sqlMSSQL2K] then
              Result := 24
            else
              Result := 0;
          else Result := 0;
        end;
      end;

    begin
      Result := 0;
      while IsIdentChar(Str^) do  // Always true until Str=''
      begin
        Result := (2 * Result + GetOrd) and $FFFFFF;
        inc(Str);
      end;
      Result := Result and $FF; // 255
      fStringLen := Str - fToIdent;
    end;

如何最好地解决这个问题?
我觉得很奇怪,这个代码仍然不是 64 位证明

pointers delphi 64-bit delphi-12-athens
1个回答
0
投票

问题是由使用 while 循环引起的。在执行

fStringLen := Str - fToIdent;
时,它已经指向超过字符串长度的内存,这会导致范围检查错误。

考虑这个简单的 while 循环示例,其中我有简单的整数作为控制值。

while I < 10 do
begin
  Memo1.Lines.Add('LoopN: ' +IntToStr(I));
  Inc(I,1);
end;
Memo1.Lines.Add('Value of I after loop is: '+IntToStr(I));

您可能期望 while 循环结束后控制变量

I
的值将为 9,但事实并非如此。事实上是10。为什么呢?

这是因为整个循环在每个循环开始之前检查控制变量的值。但我在上一个循环周期中增加了控制变量的值超过了所需的范围。

因此,您可能需要在增加

Str
的值之前计算循环内的 fStringLen。

while IsIdentChar(Str^) do  // Always true until Str=''
begin
  Result := (2 * Result + GetOrd) and $FFFFFF;
  fStringLen := Str - fToIdent;
  inc(Str);
end;

但是,这将导致字符串中的每个字符的

fStringLen 
被更新。

如果您想避免这种情况并在循环后仍然计算

fStringLen
,则需要将
Str
的值减少 1,以便它显示到字符串中最后一个字符的位置。

© www.soinside.com 2019 - 2024. All rights reserved.