[英]Debugging exception thrown in Objective-C and Xcode
我是Microsoft的開發人員,我是使用Xcode進行iPhone開發的新手。 所以,我正在閱讀一本書,並通過示例嘗試自學如何使用Objective-C編寫iPhone應用程序。 到目前為止,一切都很好,但是偶爾我會在運行時遇到通用的' objc_exception_throw
'消息。 發生這種情況時,很難找到此異常的來源。 經過一些反復試驗,我找到了答案。 其中一個參數拼寫錯誤。
正如你在下面看到的那樣,我錯過了'otherButtonTitles'參數,省略了第二個't'按鈕。
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Date and Time Selected"
message:message
delegate:nil
cancelButtonTitle:@"Cancel"
otherButonTitles:nil];
這花費我時間的原因是代碼構建成功。 這是Objective-C編譯器的正常行為嗎? 當我像這樣做一個常見的語法錯誤時,我習慣於在.NET編譯器中使構建失敗。 是否有編譯器設置我可以更改以在構建這些錯誤時使構建失敗?
首先,打開~/.gdbinit
(這是你的主目錄中名為.gdbinit
的文件 - 是的,以點開頭)並將其放入其中:
fb -[NSException raise]
fb objc_exception_throw
fb malloc_error_break
這將使用三個默認斷點初始化GDB,當它們發生時,GDB將暫停您的應用程序並向您顯示堆棧跟蹤。 這與Xcode非常好地集成,因此只要在某處發生異常或malloc失敗,您就可以通過單擊堆棧跟蹤元素來很好地遍歷代碼。
然后,打開項目的“ Get Info
面板(或選擇項目(“ Groups & Files
中的頂部項目)並點擊cmd-i
),轉到“ Build
選項卡,將項目的Base SDK
為Device - iPhone OS [someversion]
。 一直滾動到底部,找到GCC 4.0 - Warnings
部分。 那里; 打開盡可能多的警告,但請確保將“ Treat Warnings as Errors
(這相當於GCC_TREAT_WARNINGS_AS_ERRORS
)。 我個人認為:
(來源: lyndir.com )
您現在應該在代碼中遇到大多數錯誤的編譯器警告,並且在您修復代碼之前編譯器不會讓您運行代碼。 當事情確實越過編譯器的鼻子時,你應該能夠輕松找到問題,GDB在一個方便的位置破解。
你也應該看看NSZombie*
。 這些是環境變量,非常便於早期破壞不良內存分配或訪問情況。 例如; wih NSZombieEnabled
什么都不會真正被釋放; 在dealloc上它會被_NSZombie
覆蓋並且如果你再次嘗試訪問這個解除分配的內存(取消引用一個解除分配的指針),你將在GDB中獲得一些東西,而不是正常的調用,只是隨機發出數據(當然,這不是你想要的)。 有關詳細信息,請參閱 http://www.cocoadev.com/index.pl?NSZombieEnabled 。
始終使用-Werror
GCC設置( GCC_TREAT_WARNINGS_AS_ERRORS = YES
)。 您的代碼中永遠不應該出現警告,這是警告是嚴重錯誤的示例。
此外,如果您獲得objc_exception_throw
,請切換到控制台(Command-shift-R)並查找第一個“低”號地址。
2009-04-01 13:25:43.385 CrashExample[41720:20b] Stack: (
2528013804,
2478503148,
2528036920,
2528053460,
2358032430,
11076,
11880,
816174880,
345098340,
145973440,
816174880,
)
在這種情況下,它將是“11076”。 所以輸入控制台:
info line *11076
這將告訴您代碼中拋出異常的行。
拼寫錯誤的參數通常應該導致“警告:這樣的對象不響應選擇器x”在所討論的行中為黃色。 我相信默認情況下這是打開的,因為我沒有必要更改任何編譯器設置來查看這些。
此外,當我遇到未捕獲的異常時,放入gdb控制台(應該在執行應用程序時出現)並輸入以下內容以獲取所有線程的回溯有時是有益的:
taa bt
您所做的不是編譯時錯誤,因為Objective-C運行時會在運行時檢查對象是否可以響應您發送給它的消息。
我建議將此構建設置添加到目標或項目中:
GCC_TREAT_WARNINGS_AS_ERRORS = YES
它不是編譯錯誤的原因是因為將編譯時未知的消息發送到任何對象是完全有效的(並且任何對象都可以配置為動態處理消息)。 所有方法調用實際上都是發送給對象的消息。
一般來說,如果你看到任何警告,你應該解決它們,因為在大多數情況下,它們可能會導致問題(如你所見)。 這里誤導的方面是,如果您編譯一次文件並且它只有警告,如果您編譯其他類而不更改具有警告的類,則警告將不會顯示在編譯器消息中。 因此,您可能偶爾會“清理所有目標”並再次構建,以確保您不會錯過任何警告。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.