0

我正在floodfill为 iPhone 用 C 语言实现一个函数。

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

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

  2. (较小的问题)如果我尝试将RGB颜色写入大于大约(r:200,g:200,b:200,a: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;

米:

   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

4

2 回答 2

1

首先,if ((newPixel = (pixel*) malloc(...循环内部的每个都分配新的内存块,因此,循环内部有4 个分配,只有1 个释放。

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

于 2013-03-07T10:20:37.900 回答
0

您需要将释放移到块oldPixel_p 之外if,因为它总是“消耗”的。

此外,finalfree仅释放列表中的第一个元素。该列表可能包含多个元素。您需要遍历列表并释放所有剩余元素。

于 2013-03-07T10:31:18.590 回答