2011-12-03 46 views
4

當您在ObjC @catch塊中捕獲到異常時,該異常對象的生命週期是什麼?我知道我可以在塊內安全地使用它,但是如果我想在塊之後再次使用它,像這樣?@catch塊中捕獲的對象的生命週期是什麼?

NSException * exception = nil; 
@try { 
    // do something risky 
} @catch(NSException * e) { 
    exception = e; 
} 

if (exception) { 
    NSLog(@"Caught exception: %@", exception); 
} 

我可以放心地藏匿參考到另一個地方?爲了安全起見,我應該做些什麼?我可以保留它並無限期地保持它嗎?

(如果我將其分配給本地,或者稍後保留並使用,但文檔沒有真正討論此對象「來自」所有權或它是否特殊,那麼似乎工作正常我正在尋找更多的清晰度。)

回答

0

NSException繼承自NSObject,所以你可以做所有其他Objective C對象的典型做法。

不過,我建議你沒有做任何事的你的線程之外。 This O'Reilly article about Exceptions提示:

不要使用releaseautorelease消息處置的 NSException。 NSException的所有實例都放置在主要的 自動釋放池中。手動處理實例將導致錯誤 SIGSEGV

不要使用retain消息保留的NSException。 它會阻止autorelease池處置實例。這 只會導致一個微妙的內存泄漏。

...和對這些對象的一些其他有用的有用的提示。

+1

從書的建議好像沒用。這只是描述了正常的內存管理策略。它描述的問題是,如果你釋放沒有保留,或保留沒有釋放(或自動釋放)。如果你們兩個都這樣做,我想這應該不是問題。 – morningstar

+0

唯一的相關行這裏似乎是「NSException的所有實例都放置在主自動釋放池。」我希望有一個指向Apple文檔的指針說明了這一點,並且明確指出這與堆棧的關係如何從異常中解脫出來。 (例如,是它奇蹟般地放在頂部自動釋放池在它抓住了?或者它的拋出點,假設該池沒有得到清理) –

+0

我敢肯定,這意味着當前autoreleasepool – hooleyhoop

1

@catch塊做絕對沒有生命週期。這裏的隱式契約是一個NSException對象,即-raise'd或@thrown應該是一個自動釋放對象。這意味着在@catch塊中,您給出的NSException是一個自動釋放對象,就像您可能從方法調用中獲得的任何自動釋放對象一樣。您可以安全地將其存儲在本地,並在@catch塊之後引用它。

+0

這是如何發揮(如果有的話)嵌套autorelease池?我在拋出的地方得到了這個結果,你會拋出一個自動釋放的對象,但是如果它最終通過多個嵌套的autorelease池被拋出呢?如果在最後的'@ finally'塊中有'漏'字怎麼辦?這個潛在的問題只是被運行時忽略了,假設它運行良好?或者在運行時發生了一些特殊情況? –

+0

@quixoto:如果它獲得通過自動釋放池扔了,這些池會被丟棄在地上,不外流。但是,由於autorelease池的工作方式,一旦外池消耗,所有放在地板上的內池也會耗盡。不過是的,如果你在'@ finally'塊裏面有'漏',那麼我不太清楚異常是如何表現的。系統在被拋出時可能會保留它,我不知道。 –

0

NSException採用NSCopying(和NSCoding fwiw)。如果您遇到可疑的生命週期並希望明確說明,那麼複製將是理想的。

我停在那裏 - 收放可可成語流動反目成仇。

2

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Exceptions/Tasks/HandlingExceptions.html

幾乎所有NSException對象(和其他類型的異常對象的)被創建自動釋放,這將它們分配到最近的(範圍)自動釋放池。當該池被釋放時,異常被破壞。

而且,我敢肯定,某處memory programming guide,他們提到,如果沒有newalloccopy方法,他們的名字總是按照慣例返回自動釋放的對象。 NSException's methods符合資格。

輕微相關(未NSException但NSError):

如果創建一個NSError對象與initWithDomain:代碼:USERINFO:,你應該送自動釋放它,你就返回給調用者之前。

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ErrorHandlingCocoa/CreateCustomizeNSError/CreateCustomizeNSError.html

+0

很好的參考。還有就是關於頁面周圍異常自動釋放池的行爲太多,這是粘性的情況下,我在很大程度上有興趣的更詳細的討論。 –

+0

仍不能確定什麼是「幾乎所有」是指在那裏。 – user123444555621

+0

也許它只是按照慣例。當然,'[NSException提高...'將被自動釋放,但當然,你可以這樣做:'ID富= [[美孚ALLOC] INIT]。 @throw FOO;' –

相關問題