2012-01-10 101 views
0

我有一個實用工具類的靜態方法:iOS的內存管理困惑

+ (Division *) getDefaultDivision 
{ 
    Division *defaultDivision = [[Division alloc] init]; 
    defaultDivision.Id = 0; 
    defaultDivision.name = @"Accounting"; 
    defaultDivision.slug = @"accounting"; 

    return defaultDivision; 
} 

在我的ViewController我做這樣的事情:

Division *div = [[Division alloc] init]; 
div = [Utilities getDefaultDivision]; 

但是,當我分析,它說:「潛在的泄漏在x行分配並存儲到defaultDivision中的對象「。

如果使用:

Division *defaultDivision = [[[Division alloc] init] autorelease]; 

它的工作原理一次,但當我再次使用它,它崩潰。

想知道在這裏做什麼是正確的嗎?

+0

Crashlog和Stacktrace會讓它更容易幫助。 – Till 2012-01-10 21:29:53

回答

3

如果這是你的真實代碼;

Division *div = [[Division alloc] init]; 
div = [Utilities getDefaultDivision]; 

你第一次分配司並保存在DIV,那麼你得到的getDefaultDivision存儲是一個新的DIV太不釋放的第一個。

+0

好吧,現在我正在做Division * div = [Utilities getDefaultDivision];但無論如何,當我在方法對象中標記autorelease時,仍然會遇到bad_access。 – Jesse 2012-01-10 21:53:23

+0

分配之後你在使用分區做什麼?將它存儲在某處供以後使用?如果你把它存放在沒有保存的地方,autorelease發生了,你就不是一個好地方。 – 2012-01-10 22:03:26

+0

Joachim你爲我解決了這個問題。我將它存儲在appdelegate中。分配時我錯過了保留。現在工作!謝謝 – Jesse 2012-01-10 22:16:30

1

不管如何「getDefaultDivision」實施後,你有這個代碼泄漏:

Division *div = [[Division alloc] init]; 
div = [Utilities getDefaultDivision]; 

1號線分配內存,並指派div指向該內存。你在必須在某個時候釋放這個內存。但在第2行之後,這變得不可能,因爲div現在有一個新的值 - 並且指向第1行分配的內存的指針是丟失了。這是一個泄漏。直到你明白爲什麼,你纔會在薄冰上。

至於這個方法:

+ (Division *) getDefaultDivision 
{ 
    Division *defaultDivision = [[Division alloc] init]; 
    defaultDivision.Id = 0; 
    defaultDivision.name = @"Accounting"; 
    defaultDivision.slug = @"accounting"; 
    return defaultDivision; 
} 

這有時被稱爲「工廠」的方法 - 分配,初始化和一類的新實例返回參考靜態實用方法。這裏最好的做法是在工廠方法中使用autorelease。例如:

Division *defaultDivision = [[[Division alloc] init] autorelease]; 

爲什麼這是最佳實踐?根據蘋果的內存管理指南,只是在他們的下列術語方法應返回到調用方負責釋放對象的引用:

alloc, allocWithZone:, copy, copyWithZone:, mutableCopy, mutableCopyWithZone: 

- 從http://developer.apple.com/library/IOs/#documentation/General/Conceptual/DevPedia-CocoaCore/MemoryManagement.html

由於「getDefaultDivision」不是「alloc」或「copy」方法(它是一個訪問方法),那麼它不應該返回一個指向調用者以後必須釋放的對象的指針,以避免泄漏。將新分配的返回內存標記爲autorelease是遵循此合同的一種方式。

+0

不要忘記,使用'create' keywoard的函數/方法也會返回一個保留對象,至少我認爲是這種情況。 – v1Axvw 2012-01-10 21:52:12

+0

內存相關的方法命名約定是爲什麼我對ARC很開心:) – 2012-01-10 21:55:35

+0

謝謝,我現在明白了。但無論如何,當我將工廠方法標記爲autorelease,boom。 – Jesse 2012-01-10 21:55:58