3

I'm build an application that reducing the pixels width.
When I'm pressing the button of that application two or three times, Message will appear and say stack overflow.

Here's the Message :
Popup Message


Error Line on my application
Error on application
Here's my code :

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;

Why my application keep says overflow? is there any solution to fix it? or can we can exception handler? thanks

EDIT
Now my pplication says access violation.
Access Violation


It raised error in this line : nb[7] := imgval[x-1,y+1]; why it exactly happened?

3
  • OT, but also very important; have you read the warnings that your compiler produced ? They say "FOR-Loop variable ... may be undefined after loop" for kolom_gbr and baris_gbr variables... Commented Oct 21, 2014 at 8:26
  • @TLama yeah you're right. That warning appear on my compiler. So should I just write Image1.Picture.Height instead of kolom_gbr? Commented Oct 21, 2014 at 8:53
  • 1
    You can use those variables. Just not for a for loop in your context. Once you use them in a for loop, they can get random values after. But e.g. instead of for kolom_gbr := 0 to image1.Width - 1 do you could write for x := 0 to kolom_gbr - 1 do. Commented Oct 21, 2014 at 9:12

1 Answer 1

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

These variables are located on the stack and are huge. They have size 501*501*4 = 1,004,004. The default stack size is 1MB. These large arrays are the reason for your stack overflow.

You will need to use dynamically allocated arrays instead. Or avoid the need to store 2D arrays that contain information for each pixel and instead process the image in smaller sub-blocks. I've no idea whether or not that is possible because I've no idea what the code is trying to do. That's for you to work out.

Of course, one advantage of using dynamically allocated arrays is that you don't need to run the gauntlet of a buffer overrun, as you currently do. If either dimension of the image exceeds 501 then you have overrun the buffer. I do hope that you have enabled range checking in the compiler options.

for y := 0 to baris_gbr-1 do

and

for x := 0 to kolom_gbr-1 do

cannot be correct. The baris_gbr and kolom_gbr variables are not initialised since they were most recently used as loop variables. So, as well as turning on range checking, you'll want to turn on hints and warnings, and then heed them.

Sign up to request clarification or add additional context in comments.

6 Comments

I define my array for 500 because I don't know exactly the image pixels that someone choose. How can I enable range checking?
It's in the compiler options. As are the settings for hints and warnings. You cannot allocate 1MB on the stack. You'll have to use dynamic allocation. Or find a way to re-write the code to process the image in sub blocks.
Also, you really need to get out of the habit of picking arbitrary upper limits for the size of things. Your program, as written, limits the user to images with dimension no larger than 501. You might call this the "Levi's limit". There's just no need at all to impose such a limit on the user. If you must declare an array to hold user supplied data of arbitrary size, use a dynamic array.
Okay, so for the variable imgval and mark I must write array of array of integer? and later when I need to used it, for example I declare that imgval [image.height, image.width] like that?
I don't understand that comment. Allocate dynamic arrays with SetLength. Access them with [] just like constant sized arrays.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.