2013-03-07 266 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只釋放列表中的第一個元素。該列表可能有多個元素。您需要瀏覽列表並釋放所有剩餘的元素。