为什么使用Mike Heydon的TStringBuilder类会出现访问违规的情况?

4

我正在使用从.Net到Delphi 7移植的TStringBuilder类

以下是我的代码片段:

procedure TForm1.btn1Click(Sender: TObject);
const
  FILE_NAME = 'PATH TO A TEXT FILE';
var
  sBuilder: TStringBuilder;
  I: Integer;
  fil: TStringList;
  sResult: string;
  randInt: Integer;
begin
  randomize;
  sResult := '';
  for I := 1 to 100 do
  begin
    fil := TStringList.Create;
    try
      fil.LoadFromFile(FILE_NAME);

      randInt := Random(1024);

      sBuilder := TStringBuilder.Create(randInt);
      try
        sBuilder.Append(fil.Text);
        sResult := sBuilder.AsString;
      finally
        sBuilder.free;
      end;

      mmo1.Text := sResult;
    finally
      FreeAndNil(fil);
    end;
  end;
  showmessage ('DOne');
end;

我遇到了AV错误。当我创建大小是1024的倍数的内存时,可以缓解这个问题,但有时仍会出现。

我做错了什么吗?


1
该类强制实施最小缓冲区大小为1024。您的随机化没有任何作用。 - Rob Kennedy
通过随机初始缓冲区,我能够重现这个问题。 - John
1个回答

11

您的代码没有问题。您正在使用的TStringBuilder代码有误。 考虑使用此方法:

procedure TStringBuilder.Append(const AString : string); 
var iLen : integer; 
begin 
  iLen := length(AString); 
  if iLen + FIndex > FBuffMax then _ExpandBuffer; 
  move(AString[1],FBuffer[FIndex],iLen); 
  inc(FIndex,iLen); 
end;
如果未来的长度超过当前缓冲区大小,则会扩展缓冲区。_ExpandBuffer会将缓冲区的大小加倍,但一旦完成后,它就不会再检查新的缓冲区大小是否足够。如果原始缓冲区大小为1024,而您要加载的文件为3 KB,则将缓冲区大小加倍到2048仍然会使缓冲区在Append中过小,您最终会覆盖缓冲区末尾1024字节以外的内容。
在Append中将if改为while。

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