洪水填充内存泄漏iPhone

时间:2013-03-07 09:59:29

标签: objective-c c core-graphics flood-fill

我在C中为iPhone实现floodfill功能。

尽管我遇到了2个问题,但填充工作正常。

  1. 手机在几次执行下面的代码后发出内存警告。很可能是内存泄漏。另请注意, unsigned char * data (图像数据)在填充结束时是免费的()。

  2. (较小的问题)如果我尝试将 RGB 颜色写入大于的像素(r:200,g:200,b:200,a:200) )我发生了奇怪的瑕疵。解决方法是简单地限制值。

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

    下面的代码描述了我的泛洪填充算法,使用堆栈:

    ·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

2 个答案:

答案 0 :(得分:1)

首先,循环内的每个if ((newPixel = (pixel*) malloc(...分配新的内存块,因此,您在循环内部有 4 分配,并且只有 1 解除分配。 / p>

其次,我无法理解你为什么不简单地在堆栈上使用对象?你真的需要在上分配 newPixel oldPixel 等等吗?审查实现,可能有更简单的方法来实现相同的,而不管理内存问题。

答案 1 :(得分:0)

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

此外,最终free仅释放列表中的第一个元素。该列表可能包含多个元素。您需要逐步浏览列表并释放所有剩余元素。