2

我正在尝试清除 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;
4

2 回答 2

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 如何在 deplhi
覆盖许多使用过的数据时使用此过程获取两个不同的文件。
当他有足够的数据被覆盖时,他会得到一个堆栈溢出错误。

于 2013-04-03T22:17:40.497 回答
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);
于 2013-04-03T20:23:20.437 回答