按下delphi按钮时堆栈溢出

The*_*sia 3 stack-overflow delphi

我正在构建一个减少像素宽度的应用程序.
当我按下该应用程序的按钮两三次时,将显示消息并说堆栈溢出.

这是消息:
弹出消息


我的应用程序上的错误行
申请时出错
这是我的代码:

procedure TForm1.cariThin();
var
  baris_gbr, kolom_gbr, x, y, a, b, i, j, p1, p2, n : integer;
  imgval : array [0..500,0..500] of integer;
  mark : array [0..500,0..500] of integer;
  nb : array [1..9] of integer;
  hasdelete: boolean;
  R, G, BL, AB : integer;
begin
  Image3.Width := Image1.Width;
  Image3.Height := Image1.Height;

  baris_gbr := Image1.Picture.Height;
  kolom_gbr := Image1.Picture.Width;


  For kolom_gbr:= 0 To image1.Width - 1 Do
  Begin
    For baris_gbr:= 0 To image1.Height - 1 Do
     Begin
      R:= GetRValue(image1.Canvas.Pixels[kolom_gbr, baris_gbr]);
      G:= GetGValue(image1.Canvas.Pixels[kolom_gbr, baris_gbr]);
      BL:= GetBValue(image1.Canvas.Pixels[kolom_gbr, baris_gbr]);
      AB:= (R + G + BL) Div 3;

      if (AB > 200) then
      begin
        Image1.Canvas.Pixels[kolom_gbr, baris_gbr] := rgb(255,255,255);
      end
      else
      begin
        Image1.Canvas.Pixels[kolom_gbr, baris_gbr] := rgb(0,0,0);
      end;
    End;
  End;

  for y := 0 to baris_gbr-1 do
  begin
    for x := 0 to kolom_gbr-1 do
    begin
      if (Image1.canvas.pixels[x,y] = clBlack) then
      begin
        imgval[x,y] := 1;
      end
      else
      begin
         imgval[x,y] := 0;
      end;
    end;
  end;

  hasdelete := True;
  while (hasdelete) do
  begin
    hasdelete := False;
    for y := 0 to baris_gbr-1 do
    begin
     for x := 0 to kolom_gbr-1 do
     begin
        if (imgval[x,y] = 1) then
        begin
          for n:=1 to 8 do
          begin
            nb[n] := 0;
            nb[1] := imgval[x,y];
            nb[2] := imgval[x,y-1];
            nb[3] := imgval[x+1,y-1];
            nb[4] := imgval[x+1,y];
            nb[5] := imgval[x+1,y+1];
            nb[6] := imgval[x,y+1];
            nb[7] := imgval[x-1,y+1];
            nb[8] := imgval[x-1,y];
            nb[9] := imgval[x-1,y-1];
            a := 0;
          end;

          for i:= 2 to 8 do
          begin
            if ((nb[i] = 0) AND (nb[i+1] = 1)) then
            begin
              inc(a);
            end;
          end;

          if ((nb[9] = 0) AND (nb[2] = 1)) then
          begin
            inc(a);
          end;

          b := nb[2] + nb[3] + nb[4] + nb[5] + nb[6] + nb[7] + nb[8] + nb[9];
          p1 := nb[2] * nb[4] * nb[6];
          p2 := nb[4] * nb[6] * nb[8];

          if ((a = 1) AND ((b>=2) AND (b <= 6)) AND (p1 = 0) AND (p2 = 0)) then
          begin
            mark[x,y] := 0;
            hasdelete := true;
          end
          else
          begin
            mark[x,y] := 1;
          end
        end
        else
        begin
          mark[x,y] := 0;
        end;
      end;
    end;

    for y:=0 to baris_gbr-1 do
    begin
      for x:=0 to kolom_gbr-1 do
      begin
        imgval[x,y] := mark[x,y];
      end;
    end;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

为什么我的应用程序会说溢出?有没有解决方案来解决它?或者我们可以异常处理程序吗?谢谢

编辑
现在我的应用程序说访问违规.
访问违规


它在这一行引起了错误:nb [7]:= imgval [x-1,y + 1]; 为什么它确实发生了?

Dav*_*nan 5

var
  imgval : array [0..500,0..500] of integer;
  mark : array [0..500,0..500] of integer;
Run Code Online (Sandbox Code Playgroud)

这些变量位于堆栈上并且很大.它们的尺寸为501*501*4 = 1,004,004.默认堆栈大小为1MB.这些大型数组是堆栈溢出的原因.

您将需要使用动态分配的数组.或者避免需要存储包含每个像素的信息的2D数组,而是以较小的子块处理图像.我不知道这是否可行,因为我不知道代码试图做什么.这是给你锻炼的.

当然,使用动态分配的数组的一个优点是,您不需要像目前那样运行缓冲区溢出的手套.如果图像的任一维度超过501,则表示您已超出缓冲区.我希望您已在编译器选项中启用范围检查.

for y := 0 to baris_gbr-1 do
Run Code Online (Sandbox Code Playgroud)

for x := 0 to kolom_gbr-1 do
Run Code Online (Sandbox Code Playgroud)

不能正确.在baris_gbrkolom_gbr变量不初始化,因为他们最近作为循环变量.因此,除了打开范围检查之外,您还需要打开提示和警告,然后注意它们.

  • 而且,你真的需要摆脱对事物大小挑选任意上限的习惯.您编写的程序会将用户限制为尺寸不大于501的图像.您可以将其称为"Levi's limit".完全没有必要对用户施加这样的限制.如果必须声明一个数组来保存用户提供的任意大小的数据,请使用动态数组. (2认同)