清除stringgrid时EAcessViolation

时间:2013-04-02 14:32:48

标签: delphi access-violation 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出现错误消息:'access
  违规0x00401c51:写入地址0x00316572'。流程已停止。使用步骤或运行
  继续。

当我将代码更改为此错误时,错误消失了:

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;

2 个答案:

答案 0 :(得分:4)

这通常来自不正确的分配大小(数组)。最后一个写入过程会覆盖数组的限制。哪个并不总是立即导致错误。但是,或多或少重要的数据将被覆盖

我们假设记录数为15.然后Filesize(Highscorefile)== 15。数组应为[0 .. .14]。但是你只生成14的长度!

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

所以数组是[0..13]最后一个赋值会覆盖数据。

大多数情况下,阵列后面仍有可用空间,不会注意到。

如果TSrings的某些部分被覆盖,并且您尝试释放(使用strdispose)覆盖数据,那么就会出现故障。

如果写了新代码,

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

内存将通过重新编译进行组织,然后此错误会出现在另一个地方或根本不出现。

所以取代
SetLength(SortedScores, Filesize(Highscorefile)-1);

SetLength(SortedScores, Filesize(Highscorefile));

错误将会消失。

查看我的回答https://stackoverflow.com/a/11888156/1322642

OP how to get two different file with this procedure in deplhi
覆盖许多使用过的数据 当他有足够的数据被覆盖时,他会收到堆栈溢出错误。

答案 1 :(得分:0)

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);