2011-08-03 31 views
0

我仍然通過學習內存分配和Objective-C(我的第一次運行漏洞最多隻有一次機會)。這是一個當前的問題,我希望每個人都能理解它,我已經使用了一些僞代碼,但我不相信我已經放棄了任何東西。即使變量未被使用,釋放一個指針也會導致程序崩潰

我有一些數據庫的東西一排類集,我們將使用:

@interface Row : NSObject { 
    int rowID; 
NSString *firstName; 
NSString *lastName; 
} 


我有我的數據庫類的getRow功能,看起來是這樣的:

-(Row *) getRow 
{ 
    rowPlaceholder = [[Row alloc] init];  
     ... 
    rowPlaceholder.rowID = column1; 
    rowPlaceholder.firstName = column2; 
    rowPlaceholder.lastName = column3; 
     ... 
    return [rowPlaceholder autorelease]; //<-----Problem is happening here 
} 


現在在我的ViewController中,我對這種情況有兩個重要的功能:

-(void) viewWillAppear:(BOOL)animated{ 
currentRow = [[Row alloc] init]; 
currentRow = getRow; 
firstNamelabel.text = currentRow.firstName; 
} 


第二個功能是一個按鈕被第二個字:

-(IBAction)btnLastName:(id)sender{ 
lastNamelabel.text = currentRow.lastName; //<---Crashes the program 
} 


所以,你可以看到,使用currentRow針對導致程序崩潰,並且我所能不明白的是,如果我不釋放rowPlaceholder該程序工作正常。此時爲什麼currentRow關心來自另一個函數的數據,因爲它已經擁有了它想要的東西(來自getRow()的一個值)。

回答

1

autorelease表示有問題的對象會自動釋放。當發生這種情況與自動釋放池被清空時相關聯,但對於默認情況下,當UI「出現空氣」時 - 當您的調用鏈返回到UI系統代碼時。如果你想要「跨越」這樣的UI系統代碼返回,你需要明確保留它。一般來說,使其成爲一個保留屬性是最好的方式來做到這一點(當然,你需要清除/釋放dealloc方法中的屬性)。

[你們爲什麼這樣做:]

currentRow = [[Row alloc] init]; 
currentRow = getRow; 
+0

後者是我的錯誤。你能向我解釋在內存方面發生了什麼?當我做這樣的回報時,它只是被返回的指針嗎?所以最後,這兩個指針都指向了內存中的同一個位置,直到有人被自動釋放,讓另一個困惑? – ballofpopculture

+0

您分配了一個新的Row對象並將其分配給currentRow。然後你明顯地將一個不同的Row對象分配給currentRow。第一個對象仍然存在(儘管你不能再解決它),被保留(通過'alloc'),並且是「泄漏」。 –

+0

至於你的崩潰,這很可能是因爲,在'viewWillAppear'和調用'btnLastName'的按鈕push之間,autorelease池被清空(因爲它應該是,當UI出現空氣時),以及結果你的Row對象已經走了。 –

2

這是怎麼回事?

currentRow = [[Row alloc] init]; 
currentRow = getRow; 

您創建行,然後覆蓋它。我甚至不知道什麼getRow就是在這種背景下。這是沒有辦法編譯沒有警告。無論如何,嘗試使用:

currentRow = [[self getRow] retain]; 

(雖然,對於公約的份上,你應該調用方法只是row

沒有看到您的getRow方法或類的其餘部分,我不能告訴爲什麼問題會在那裏發生。

+0

有趣的是,它在構建時不會引發任何警告,但應該是顯而易見的,就像瘋狂泄漏一樣。保留似乎正在工作。 – ballofpopculture

+0

+1 [...保留]。我認爲'getRow'只是OP的一個錯字。 –

0

當你分配並初始化rowPlaceholder,然後將它作爲自動釋放返回時,這意味着它有效地準備好通過內存管理進行清理,除非其他對象保留它。

在行:

currentRow=getRow 

你所得到的指針,指向的getRow返回的對象的副本,但似乎並沒有被保留它。 (並且在返回之前getRow會自動釋放它)。

如果currentRow是您的類的屬性,那麼您需要將其稱爲this.currentRow以確保調用訪問器方法(並且必須將其聲明爲retain屬性)。如果它沒有聲明爲一個屬性,並且只是你的類的屬性,那麼你需要手動保留它。

您第一次引用currentRow.firstName是好的,因爲當前執行線程沒有失去控制權,所以autorelease池還沒有清理這個內存。

但是,一旦你的線程失去了控制並給內存管理一個清理它的機會,當你回到btnLastName方法時,currentRow指向的內存(這是指向分配給rowPlaceHolder = [[row alloc] init]調用)已經發布。

相關問題