2011-12-13 43 views
6

我的一個朋友發現了NSDictionary的一些奇怪的行爲,我很好奇它爲什麼會發生。請看下面的代碼:爲什麼這個Objective C調用似乎掛起?

NSDictionary *dict = [[NSDictionary alloc] init]; 

// Oops, we can't mutate an NSDictionary 
[dict setObject:[[NSNull alloc] init] forKey:@"test"]; 
NSLog(@"Set"); 

的代碼在編譯時說:「‘NSDictionary的’可能不‘:forKey:的setObject’反應」會產生一個警告。這一切都很好,如果你想運行它,你就會得到這個產量在控制檯:

- [__ NSCFDictionary的setObject:forKey:]:變異的方法發送到不可變對象

再次,正是你期望發生的事情。但是,此時應用程序不會因崩潰或由於未捕獲的異常而終止。 setObject:forKey:方法根本不會返回,並且該應用程序似乎掛起;以下NSLog永遠不會執行。如果嘗試使用GDB進行該方法,調試似乎結束,但沒有任何明確的錯誤消息。該應用程序繼續運行,但調試器不知道代碼中執行「卡住」的位置。

這是怎麼回事?在這種情況下,應用程序實際上在做什麼?爲什麼它不會因NSInternalInconsistencyException或其他類似事件而崩潰?

編輯:對於那些問過,我在OS X Lion(10.7.2)上運行XCode 4.1,用「Apple LLVM 2.1編譯器」構建。我正在使用XCode 4中新Cocoa項目的所有默認設置。無論是調試程序還是「運行」,我都會遇到同樣的非崩潰行爲。從調試版本更改爲發佈版本沒有任何區別。我甚至可以在Finder中手動定位.app文件,然後雙擊它在XCode之外執行它,但它仍然不會崩潰。

+1

嘗試在調試器下運行它;我敢打賭它很難崩潰。我發現調試器環境可能會對運行時環境產生一些意想不到的影響,特別是在異常情況下,以及在你點擊它們時會發生什麼。 – 2011-12-14 00:19:30

+2

當拋出異常時,控件將繼續捕獲異常,*不在異常後的下一行。在你的例子中,調試器或者運行時的「腸子」「抓住」了這個異常。在任何情況下,你都不會期望NSLog在-setObject:forKey之後發生:拋出一個異常。 – 2011-12-14 00:38:39

回答

1

異常不會使AppKit程序崩潰。 NSApplication會安裝一個默認的異常處理程序,以捕獲您的代碼無法執行的異常。然後你就像往常一樣回到runloop。

許多應用程序都表現出這種行爲。這是莫名空白的視圖/窗口的常見原因。如果在視圖管理完成繪製之前發生異常,視圖將爲空白,但應用程序不會崩潰。如果故意將缺省異常處理程序更改爲崩潰,異常只會導致崩潰。

相關問題