2017-04-19 88 views
2

嗨,我正在做一个简单的绘画程序来学习SDL和C,当我运行我的代码时出现分割错误,我想这是因为它试图填充窗口外的像素,但我是不知道如何阻止这种情况的发生。 有没有办法阻止递归访问窗口之外? 这是代码:抱歉,它是多么混乱。如何解决递归洪水填充分段错误?

void floodfill(SDL_Surface *canvas,int SCREEN_WIDTH, int SCREEN_HEIGHT, int x, int y, int boundingX, int boundingY, Uint32 src, Uint32 fillcolour) 
{ 

Uint32 clickedColour = getPixel(canvas, x, y); 
Uint32 boundingColour = getPixel(canvas, boundingX, boundingY); //make sure you are not exceeding the limits of the window. 

printf("floodfill Inside\n"); 
printf("X&Y co-ords %d,%d\n",x,y); 

if (src==fillcolour) 
    return; 

if (x <= 0 || x <= SCREEN_WIDTH || y <= 0 || y <= SCREEN_HEIGHT) 
{ 
    printf("saying things!\n"); 
    return; 
} 

printf("%d,%d\n",x,y); 

if (fillcolour != clickedColour) 
    putPixel(canvas, x, y, fillcolour); 

if (clickedColour !=boundingColour) 
    return; 

if ((x>=0 && x<SCREEN_WIDTH) && (y>=0 && y<SCREEN_HEIGHT)) 
{ 
    putPixel(canvas, x, y, fillcolour); 
    printf("put Pixel x=%d and y=%d\n", x, y); 
} 

floodfill(canvas,SCREEN_WIDTH, SCREEN_HEIGHT, x, y+1, x, y+2, src, fillcolour); 
floodfill(canvas,SCREEN_WIDTH, SCREEN_HEIGHT, x, y, x+2, y, src, fillcolour); 
floodfill(canvas,SCREEN_WIDTH, SCREEN_HEIGHT, x, y, x, y+2, src, fillcolour); 
floodfill(canvas,SCREEN_WIDTH, SCREEN_HEIGHT, x+1, y, x+2, y, src, fillcolour); 

}

+0

当然,如果您认为自己不在绘图空间之外,您应该在函数的开头部分进行一些检查以确保您位于正确的区域内? –

+0

输出的最后一行打印行是什么? –

+2

条件if(x <= 0 || x <= SCREEN_WIDTH)没有任何意义。 –

回答

0

任何递归执行洪水填充将与段错误崩溃的足够大的输入:

它穿越像素的深度 - 第一种方式,这意味着递归调用的数量与填充洪泛的区域的大小成线性增长。由于像素很小,堆栈框架比较大,堆栈空间有限(通常大约为单位数量的mebabytes),即使是小图像也会导致堆栈空间耗尽,并导致进程崩溃。

因此,您可以安全地避免这种情况的唯一方法是重新实现您的算法,以便它使用循环而不是递归调用。 这方面有两个变种:

  1. 迭代实现深度优先算法与一个明确的堆栈。这允许更深的“递归”,因为显式堆栈的缓冲区可能大于调用堆栈,并且您通常会为每个递归级别将更少的数据推送到堆栈。

  2. 使用宽度优先算法。这可能更节省空间,因为在图像上移动的正面会趋向于更小。

1

我不熟悉SDL,但起码你的边界检查不完全正确。通用C /使用递归C++溢出测试算法的实现可能看起来像:

// Dimentions for screen to paint, in this case 10x10 matrix 
#define SCREEN_HEIGHT 10 
#define SCREEN_WIDTH 10 

void floodFillTest(int x, int y, int old_color, int new_color, int matrix[][SCREEN_HEIGHT]) 
{ 
    // Check boundaries 
    if (x < 0 || x >= SCREEN_WIDTH || y < 0 || y >= SCREEN_HEIGHT) 
     return; 

    // Check color to fill boundaries 
    if (matrix[x][y] != old_color) 
     return; 

    // Replace old color at (x, y) 
    matrix[x][y] = new_color; 

    floodFillTest(x+1, y, old_color, new_color, matrix); // Recur east 
    floodFillTest(x-1, y, old_color, new_color, matrix); // Recur west 
    floodFillTest(x, y+1, old_color, new_color, matrix); // Recur south 
    floodFillTest(x, y-1, old_color, new_color, matrix); // Recur north 
}