Почему я получаю нарушения прав доступа с помощью класса TStringBuilder Майка Хейдона? - PullRequest
4 голосов
/ 08 августа 2011

Я использую класс TStringBuilder , портированный из .Net в Delphi 7.

А вот мой фрагмент кода:

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 Ответ

11 голосов
/ 08 августа 2011

Ваш код в порядке.Используемый вами код 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 КБ, то удвоение размера буфера до 2048 по-прежнему приведет к тому, что буфер будет слишком мал в Append, и в результате вы перезапишете 1024 байта за пределы конца.буфера.

Измените if на while в Append.

...