2013-03-07 264 views
0

我正在C中为iPhone实施floodfill函数。泄漏填充内存泄漏iPhone

填充工程,虽然我有2个问题。

  1. 手机下面的代码的几个处决后,给出了一个内存警告。很可能是内存泄漏。还要注意,无符号字符*数据(图像数据)在填充结束时被释放()。

  2. (较小的问题)如果我试图写RGB的颜色是比约更大的像素(R:200,G:200,B:200,200)我得到奇怪的伪像发生。解决方法是简单地限制值。

我怀疑这两个问题之间可能存在相关性。

下面的代码描述我的洪水填充算法,采用堆栈:

.H:

typedef struct { 
    int red; 
    int green; 
    int blue; 
    int alpha; 
} GUIColor; 


struct pixel_st { 
    int x; 
    int y; 
    struct pixel_st *nextPixel; 
}; 
typedef struct pixel_st pixel; 

.M:

void floodFill(CGPoint location, GUIColor tc, GUIColor rc, size_t width, size_t height, unsigned char *data){ 
    if (isGUIColorEqual(tc, rc)) return; 

    pixel* aPixel = (pixel *) malloc(sizeof (struct pixel_st)); 
    NSLog(@"sizeof aPixel : %i",(int)sizeof(aPixel)); 

    (*aPixel).x = location.x; 
    (*aPixel).y = location.y; 
    (*aPixel).nextPixel = NULL; 

    int i = 0; 

    NSLog(@"Replacement color A%i, R%i, G%i, B%i",rc.alpha,rc.red,rc.green, rc.blue); 

    while (aPixel != NULL){ 
     pixel *oldPixel_p = aPixel; 
     pixel currentPixel = *aPixel; 
     aPixel = currentPixel.nextPixel; 


     //Now we do some boundary checks 
     if (!isOutOfBounds(currentPixel.x, currentPixel.y, width, height)){ 
      //Grab the current Pixel color 
      GUIColor currentColor = getGUIColorFromPixelAtLocation(CGPointMake(currentPixel.x, currentPixel.y), width, height, data); 

      if (isGUIColorSimilar(currentColor, tc)){ 
       //Colors are similar, lets continue the spread 
       setGUIColorToPixelAtLocation(CGPointMake(currentPixel.x, currentPixel.y), rc, width,height, data); 

       pixel *newPixel; 


       if ((newPixel = (pixel*) malloc(sizeof(struct pixel_st))) != NULL) { 
        (*newPixel).x = currentPixel.x; 
        (*newPixel).y = currentPixel.y-1; 
        (*newPixel).nextPixel = aPixel; 
        aPixel = newPixel; 

       } 
       if ((newPixel = (pixel*) malloc(sizeof(struct pixel_st))) != NULL) { 
        (*newPixel).x = currentPixel.x; 
        (*newPixel).y = currentPixel.y+1; 
        (*newPixel).nextPixel = aPixel; 
        aPixel = newPixel; 
       } 
       if ((newPixel = (pixel*) malloc(sizeof(struct pixel_st))) != NULL) { 
        (*newPixel).x = currentPixel.x+1; 
        (*newPixel).y = currentPixel.y; 
        (*newPixel).nextPixel = aPixel; 
        aPixel = newPixel; 
       } 
       if ((newPixel = (pixel*) malloc(sizeof(struct pixel_st))) != NULL) { 
        (*newPixel).x = currentPixel.x-1; 
        (*newPixel).y = currentPixel.y; 
        (*newPixel).nextPixel = aPixel; 
        aPixel = newPixel; 
       } 
       free(oldPixel_p); 
       i ++; 
       if (i == width * height * 4 * 5) break; 

      } 


     } 
    } 

    free(aPixel); 
} 

这个实现的堆栈是基于ObjFloodFill在此处找到的:

https://github.com/OgreSwamp/ObjFloodFill/blob/master/src/FloodFill.m

+1

为什么分配内存一次,然后释放内部多次while循环 – hazzelnuttie 2013-03-07 10:07:12

+0

该堆栈是基于ObjFloodFill,我将它移植到我的代码,但我没有很多经验,直C内存管理,所以我我不确定。 – Ospho 2013-03-07 10:14:22

+0

在页面的顶部,它被记录为“OgreSwamp2年前 添加了对ScanlineFloodfill的注释,它不起作用” – hazzelnuttie 2013-03-07 10:20:25

回答

1

首先,每个if ((newPixel = (pixel*) malloc(...循环内分配新的内存块,所以,你必须在循环内拨款,只有释放。

其次,我不明白你为什么不简单地使用栈上的对象?你真的需要分配newPixel,oldPixel等等?查看实现,可能有更简单的方法来实现同样的内容,而且根本不管理内存问题。

+0

虽然有可能,但我不确定如何去做,我以前使用递归函数floodfill,但是会由于堆栈溢出而导致设备崩溃(在iOS模拟器上它会工作)。 – Ospho 2013-03-07 10:29:00

0

您需要将oldPixel_p的取消分配移动到if块之外,因为它总是被“消耗”。

此外,最后的free只释放列表中的第一个元素。该列表可能有多个元素。您需要浏览列表并释放所有剩余的元素。