按下delphi按钮时堆栈溢出

时间:2014-10-21 08:23:13

标签: delphi stack-overflow

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

这里是留言:
Popup Message


我的申请上的错误行
Error on application
这是我的代码:

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;

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

编辑
现在我的申请说违反了访问权限。
Access Violation

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

1 个答案:

答案 0 :(得分:5)

var
  imgval : array [0..500,0..500] of integer;
  mark : array [0..500,0..500] of integer;

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

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

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

for y := 0 to baris_gbr-1 do

for x := 0 to kolom_gbr-1 do

无法正确。 baris_gbrkolom_gbr变量未初始化,因为它们最近被用作循环变量。因此,除了启用范围检查之外,您还需要打开提示和警告,然后注意它们。