EAcessViolation при очистке stringgrid

Я пытаюсь очистить stringgrid, но получаю сообщение о несогласованном нарушении прав доступа, которое появляется после очистки последнего столбца. Вот код:

procedure ClearTable;
var
i:integer;
begin
  for i := 0 to 3 do
    begin
      frmHighscores.HighscoreTable.Cols[i].Clear;
    end;
end;

И вот процедура, которая его вызывает:

procedure TfrmHighscores.sortbtnClick(Sender: TObject);
var
SortedScores :array of Thighscore;
i: integer;
Ascending:boolean;
begin
  ClearTable;
  Case sortRGP.ItemIndex of
   0: Ascending := False;
   1: Ascending :=True;
  end;
  AssignFile(HighScoreFile, 'HighScoreFile.DAT');
  Reset(HighScoreFile);
  If Filesize(Highscorefile) <= 1 then
    begin
      showmessage('There arent enough items to sort!');
    end;
  If Filesize(Highscorefile) > 1 then
    begin
      SetLength(SortedScores, Filesize(Highscorefile)-1);
      i:=0;
      While not eof(HighScoreFile) do
        begin
          Read(Highscorefile, Highscore[i+1]);
          sortedScores[i].Name := Highscore[i+1].Name;
          sortedScores[i].Score := Highscore[i+1].Score;
          sortedScores[i].DateSet := Highscore[i+1].DateSet;
          sortedScores[i].Difficulty := Highscore[i+1].Difficulty;
          inc(i);
        end;
    Closefile(highscorefile);
    Quicksort(SortedScores, Low(SortedScores), High(SortedScores)+1, Ascending);
    end;
end;

Сообщение об ошибке, когда я пытаюсь запустить его,

Ошибка проекта C:\Users\Owner\V0.66\Project1.exe с сообщением: «Нарушение доступа
по адресу 0x00401c51: запись адреса 0x00316572». Процесс остановлен. Используйте Step или Run
, чтобы продолжить.

Ошибка исчезает, когда я меняю код на это:

procedure ClearTable;
var
i:integer;
begin
  for i := 0 to 3 do
    begin
      showmessage('Attempting to clear Col ' +inttostr(i));
      frmHighscores.HighscoreTable.Cols[i].Clear;
      showmessage('Col ' +inttostr(i) + ' cleared successfully');
    end;
end;

person jatsb    schedule 02.04.2013    source источник


Ответы (2)


Это часто происходит из-за неправильных размеров распределения (массива). Последний процесс записи переопределяет пределы массива. Которые не всегда сразу приводят к ошибке. Но более или менее важные данные будут перезаписаны.

Предположим, что количество записей равно 15. Тогда Filesize(Highscorefile) == 15 . Массив должен быть [0.. .14]. Но вы генерируете только длину 14 !

SetLength(SortedScores, Filesize(Highscorefile)-1); == 14.

Итак, массив равен [0..13]. Последнее присваивание перезаписывает данные.

В основном за массивом еще есть свободное место и его не заметишь.

Если части TSring перезаписаны, и вы пытаетесь освободить (с помощью strdispose) перезаписанные данные, то возникает ошибка.

Если новый код написан,

showmessage('Attempting to clear Col ' +inttostr(i));

Память будет заново организована с помощью перекомпиляции, и тогда эта ошибка появится в другом месте или вообще не появится.

Поэтому замените
SetLength(SortedScores, Filesize(Highscorefile)-1);
на
SetLength(SortedScores, Filesize(Highscorefile));

И ошибка исчезнет.

взгляните на мой ответ https://stackoverflow.com/a/11888156/1322642

OP как получить два разных файла с помощью этой процедуры в deplhi
перезаписывая многие используемые данные.
И когда у него достаточно перезаписанных данных, он получает ошибку переполнения стека.

person moskito-x    schedule 03.04.2013

frmHighscores является экземпляром TfrmHighscores?

попробуйте сделать процедуру ClearTable приватной для TfrmHighscores и вызовите:

HighscoreTable.Cols[i].Clear;

вместо

frmHighscores.HighscoreTable.Cols[i].Clear;

или вы можете попробовать передать ссылку формы на процедуру:

procedure ClearTable(AFrmHighScores: TfrmHighscores);
var
i:integer;
begin
  for i := 0 to 3 do
    begin
      showmessage('Attempting to clear Col ' +inttostr(i));
      AFrmHighScores.HighscoreTable.Cols[i].Clear;
      showmessage('Col ' +inttostr(i) + ' cleared successfully');
    end;
end;

вызов его в коде:

ClearTable(Self);
person Agustin Seifert    schedule 03.04.2013