2010-01-27 119 views
2

我有以下的實例方法(改編自上市的iPhone應用程序編程指南中的事件處理部分的3-6):當函數返回malloc()的結果時,如何在malloc()後釋放()?

- (CGPoint)originOfTouch:(UITouch *)touch 
{ 
    CGPoint *touchOriginPoint = (CGPoint *)CFDictionaryGetValue(touchOriginPoints, touch); 
    if (touchOriginPoint == NULL) 
    { 
     touchOriginPoint = (CGPoint *)malloc(sizeof(CGPoint)); // leaks 
     CFDictionarySetValue(touchOriginPoints, touch, touchOriginPoint); 
     *touchOriginPoint = [touch locationInView:touch.view]; 
    } 
    return *touchOriginPoint; 
} 

每一次,而我的應用程序泄漏16個字節結果致電malloc()。我不知道如何返回touchOriginPointfree()也是如此。

回答

3

如果你不在乎輕微性能損失,使用NSMutableDictionary和點保存爲NSValue

NSValue* touchOriginPointValue = [touchOriginPoints objectForKey:touch]; 
if (touchOriginPointValue == nil) { 
    touchOriginPointValue = [NSValue valueWithCGPoint:[touch locationInView:touch.view]]; 
    [touchOriginPoints setObject:touchOriginPointValue forKey:touch]; 
} 
return [touchOriginPointValue CGPointValue]; 

如果你必須使用CFDictionary方法,你必須找到一個當不需要這些值時,將這些地址設置爲free那些malloc -ed內存。因此,你必須通過價值創造的回調字典

static void free_malloced_memory (CFAllocatorRef allocator, const void *value) { 
    free((void*)value); 
} 
static const CFDictionaryValueCallBacks values_callbacks = {0, NULL, free_malloced_memory, NULL, NULL}; 
... 
touchOriginPoints = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, & values_callbacks); 
... 
+0

感謝KennyTM,我會給這些回調函數一個鏡頭。 – 2010-01-27 16:24:30

+0

CFDictionary是必需的,因爲UITouch不執行NSCopying。雖然實現回調函數有助於它不會消除所有相關的內存泄漏。 – 2010-02-02 15:18:22

+0

@Shaun:對啊。但是由於複製是唯一的問題,您仍然可以使用'CFDictionary'作爲鍵,'NSValue'作爲值,並使用'&kCFTypeDictionaryValueCallBacks'值回調,以便CF可以自動跟蹤ref-counting。 – kennytm 2010-02-02 15:43:28

1

如果您必須從函數返回malloc'd值,那麼您已經將釋放內存的責任傳遞給調用函數或其調用者之一。

由於我們無法看到調用函數,我們無法再診斷。

0

如果你要返回一個分配的對象,那麼你需要調用者free()它,否則你需要使用某種垃圾回收(所以它會自動釋放)。

+0

2秒後我的答案...:D – 2010-01-27 07:31:31

+1

iPhoneOS中沒有GC。 – kennytm 2010-01-27 07:31:52

+0

iPhoneOS中沒有GC是非常可悲的。我意識到這是一個iPhone的具體評論,但我的答案是一個通用的。 – vy32 2010-01-27 16:50:45

0

你實際上並沒有返回一個指針時,該值將被複制到一個臨時值返回時,這樣你就不會真正返回分配的問題是,你只是沒有釋放它,你將分配添加到字典,並將它留在那裏?

有沒有像EndOfTouch功能?你從字典中刪除觸摸嗎?如果有的話,請撥打免費的分配在那裏,你應該沒問題

+0

有一個touchesEnded方法,我釋放這些分配,但我發現,當觸摸委託被中途刪除時,該方法永遠不會被觸發,導致孤立的分配。 – 2010-01-27 16:25:56

+0

嗯,觸摸代表如何移除? (我不太熟悉iphone或objC)。你能通過你的名單,然後釋放一切嗎?除此之外,你可以有一個實際對象的字典,而不是一個指針字典嗎?(我不知道CFDictionaryGetValue如果找不到答案會如何返回......) 那樣將不會獲得免費撥款。 – matt 2010-01-27 23:09:59