Why is there a stack overflow in this code?

I wrote this function to fill a closed loop, pixvali is declared globally to store the color value of the pixel where the first click will be made (inside the closed loop).

But the problem is that this recursion doesn't end when its first * fill (.., ..) * ends and it says the stack is overflowed ...

void fill(int x,int y)
{
    GLfloat pixval[3];
    glReadPixels(x,y,1,1,GL_RGB,GL_FLOAT,pixval);
    if(pixval[0]==pixvali[0] && pixval[1]==pixvali[1] && pixval[2]== pixvali[2])
    {
        glBegin(GL_POINTS);
            glVertex2i(x,y);
        glEnd();
        glFlush();
        fill(x-1,y);
        fill(x+1,y);
        fill(x,y-1);
        fill(x,y+1);
    }   
}

      

0


a source to share


7 replies


implement your own stack, don't use recursion to fill the fill unless you are filling shapes with a relatively small surface area in pixels.

typical implementation:



Stack stack; 
stack.push(firstPoint);

while(!stack.isEmpty()){
   Point currentPoint= stack.pop();
   //do what ever you want to do here, namely paint.
   //boundary check ur surrounding points and push them in the stack if they are inbounds
}

      

0


a source


Stack overflow occurs because you are using recursion and the depth of the recursion is linear in the number of pixels in the form you fill out.



It is also possible that you are trying to fill a shape with the same color as it. That is, the current gl color is the same as pixvali. In this case, you will end up with infinite recursion.

+4


a source


It's hard to tell on this point, but I am assuming that you will start moving in a pixel loop.

For example, think that you only have 4 pixels that you need for a color (0,0), (0,1), (1,0), (1,1).

You start coloring (0,0). Then your recursion will come in (1,0) since (-1,0) doesn't need coloring. then (0,0) again, since it is the pixel which is (x-1, y) again, etc.

You need to add some way to mark the already colored pixels. But this is just a guess, because you cannot really see what is happening outside of these functions.

+3


a source


Not sure about the implementation details, but if a 12-byte local array is allocated on the stack (3 x 4 bytes each), then you have 4 bytes for the x and y parameters, and possibly four bytes for the return address. This gives at least 24 every time you recurse. This means that you only need over 40,000 calls to punch through 1MB of stack space if there is nothing else on it, which is not true.

To put this in perspective, 43'690 pixels are only about 10% of the 800x600 screen.

+1


a source


You need to check which pixels you are editing.

eg. If you have an image from 0.0 to 10.10 and you edit 11.10 you are out of memory.

So, you need to check if x, y is between the borders of the image.

x>=left&&x<=right&&y>=top&&y<=bottom 

      

+1


a source


At first glance, the algorithm looks good. I'm a little worried about "==" because they don't work with floats. I suggest using

abs(val1 - val2) < limit

      

instead of (where limit

is <1 and> 0. Try 0.0001 for example).

To track down the error, I suggest adding printf()

at the beginning of the function. When you see a function trying to fill it helps. Maybe he's stuck somewhere and calls himself over and over with the same coordinates?

In addition, the stack may be too small for the area you are trying to fill. Try a small area first, say a small rectangle that's only 4px by 3px. Don't try to click on it with your mouse, but start from a known good point inside (just put fill () in your code).

Printing the color values ​​can also help.

0


a source


Why are you overusing OpenGL for this? What you are doing there is very unstable. For example, a pixel read by glReadPixels will only correspond to the position of the vertices if a carefully chosen combination of projection matrix and model is used. Also, each fill iteration will do a full round. Just because you are using OpenGL it doesn't get magically fast.

If you want to fill some area in the framebuffer, read the entire framebuffer, fill on that and return the result back to OpenGL. Also, if some part of the framebuffer is closed (with a window or similar), those parts will not

Now to understand why you end up in infinite recursion. Consider this:

fill(4, 4)

will fill(5, 4)

cause fill(5, 5)

will fill(4, 5)

cause will cause will cause fill(4, 4)

arrow

You now have this test:

if( pixval[0] == pixvali[0] && 
    pixval[1] == pixvali[1] && 
    pixval[2] == pixvali[2] )

      

Note that this evaluates to true if the given pixel already has the target color, again terminating in an infinite recursion. You have to check for inequality.

Last but not least, an image can be made up of millions of pixels. Normal stack sizes only allow a maximum of 1000 levels of nesting of functions, so you must convert tail recursion to iteration.

TL; DR: don't use OpenGL for this, work in a local buffer, use a proper test of iteration conditions, and use iteration instead of recursion (or use a functional language, then the compiler will take care of that tail recursion).

http://en.wikipedia.org/wiki/Flood_fill

0


a source







All Articles