錯誤處理恐怕是開發過程中最讓人難受的環節之一。在正常情況下讓程式的各部分都正常工作已經是比較困難的了,乙個好的應用應該在出錯時也有得體的表現。
1. 錯誤處理模式
三種模式
1.1預期錯誤
磁碟空間不足是一種預期錯誤,雖然它極少發生,itunes在使用者裝置中裝滿了**檔案,這種情況很容易發生。當無法寫入檔案時,需要能夠優雅的恢復
對於那些會預期發生的錯誤,應該得體的進行處理,不應該讓程式崩潰。處理這種錯誤,比較通用的方式是返回乙個nserror物件的引用
1.2程式錯誤
-(void)dosomething:(nsuinteger)index
} 傳入乙個超出有效範圍的索引值是一種程式設計錯誤,這段**默默忍受了這種錯誤,沒有做出任何操作。這種問題非常難於除錯。應該傳入有效的值,這是方法呼叫者的責任。默默忽略錯誤值是nsarray能做的最糟糕的事情,讓程式崩潰會是乙個更好的選擇
1.3非預期錯誤
在ios中,分配小塊記憶體失敗是一種非預期錯誤,在正常操作中永遠不該發生。在遇到這個錯誤之前,程式應該早就收到記憶體預警訊息並且被強制結束了。
nsstring * string =[nsstring stringwithformat:@"%d",1];
nsarray * array = [nsarray arraywithobject:string];
由於foundation無法正確分配記憶體而導致stringwithformat
:方法失敗,這種情況是可能發生的。這樣會導致程式會丟擲乙個
」試圖向陣列中插入
nil」
的異常,最後很可能導致應用崩潰。
c語言程式設計一般會加乙個檢查來防止這種情況發生,
ios不需要這樣。
通常情況下可以忽略非預期錯誤,直接讓程式崩潰就好了。理由:發生概率極小;保持**簡潔;oc中為記憶體分配錯誤處理**幾乎是沒有意義。
2. 斷言
使用斷言可以有效的防止程式錯誤。斷言要求程式中特定的語句必須為真。如果不為真,說明程式正處於一種無法**的狀態,這時候程式不應該繼續執行下去。
nsassert( index != 0 , @"indexmust not be zero");
[self
dosomething:0];
控制台列印:
2013-07-13 10:31:14.466 test[8796:c07] *** assertionfailure in -[wgq_viewcontroller dosomething:],/users/king/desktop/test/test/wgq_viewcontroller.m:26
如果測試條件返回no,nsassert 就會拋乙個異常,異常處理程式捕獲異常之後,會呼叫abort結束程式。 並顯示自定義的訊息"index must not be zero"
。並同時顯示出錯檔案,出錯**,呼叫函式等訊息。他是乙個程式跟蹤的很好的手段。(c語言中使用斷言nscassert.)
mac開發,出現異常只會結束當前迴圈,ios中,結束整個程式。
xcode 4.6.3 預設情況下會禁用發布版本**中得斷言。
用法總結與注意事項:
1)在函式開始處檢查傳入引數的合法性
2) 每個nsassert 只檢驗乙個條件,因為檢驗多個條件時,當斷言失敗,無法直觀的判斷是哪個條件失敗
3)不能使用改變環境的語句,因為assert只在debug個生效,如果這麼做,會使用程式在真正執行時遇到問題 錯誤:
assert(i++< 100) 這是因為如果出錯,比如在執行之前i=100,那麼這條語句就不會執行,那麼i++這條命令就沒有執行。
正確: assert(i < 100) ;
i++;
4) assert和後面的語句應空一行,以形成邏輯和視覺上的一致感
5)有的地方,assert不能代替條件過濾
下面的**是吧nscassert 包裝為rncassert 在oc中使用斷言的時候就應該使用nsassert。
#define rnlogbug nslog
// rnassert and rncassert work exactly like nsassert andnscassert
// except they log, even in release mode
#define rnassert(condition, desc, ...) \
if (!(condition))
#define rncassert(condition, desc) \
if (!(condition))
斷言應該位於導致程式崩潰的**之前。看下面的例子
rnassert(foo !=nil,@"foo must not be nil");
[array addobject:foo];
如果這裡會導致斷言失敗,那麼關閉斷言,程式依然會崩潰。所以要將**改為下面這樣:
rnassert(foo != nil, @"foomust not be nil");
if (foo != nil)
else
這樣就保證了斷言條件跟if條件總是匹配的。這是一種比較好的斷言使用方式。另外建議在switch語句的defualt分支中使用斷言。
assert的缺點是,頻繁的呼叫會極大的影響程式的效能,增加額外的開銷。
插一點關於除錯資訊—幾個巨集 (附加內容):
1)__va_args__ 是乙個可變引數的巨集,很少人知道這個巨集,這個可變引數的巨集是新的c99規範中新增的,目前似乎只有gcc支援(vc6.0的編譯器不支援)。巨集前面加上##的作用在於,當可變引數的個數為0時,這裡的##起到把前面多餘的","去掉的作用,否則會編譯出錯, 你可以試試。
2) __file__ 巨集在預編譯時會替換成當前的源檔名
3) __line__巨集在預編譯時會替換成當前的行號
4)__function__巨集在預編譯時會替換成當前的函式名稱
3. 異常
簡單的說,在oc中,異常不是用來處理那些可恢復的錯誤的。異常是用來處理那些永遠不應該發生卻卻發生了的錯誤,而這個時候應該結束程式執行。異常跟nsassert比較像,事實上,nsassert 就是作為異常實現的。
[n***ception raise:@"webservice error" format:@"%@",@"
測試111111"];
程式丟擲異常的原因多種多樣,可由硬體導致也可由軟體引起。異常的例子很多,包括被零除、下溢和上異之類的數學錯誤,呼叫未定義的指令(例如,試圖呼叫乙個沒有定義的方法 )以及試圖越界訪問群體中的元素
網上找的例子:
n***ception* ex = [[n***ceptionalloc]initwithname:@"myexception" reason:@"b==0" userinfo:nil];
@try
}
@catch (n***ception *exception)//
捕獲丟擲的異常
@finally
[exrelease];
典型應用:
@try
@catch(n***ception *exception)
return a;
以下內容出自 exception programming topics :
cocoa框架通常不是異常安全的。異常只用來處理程式設計師犯的錯誤,程式捕獲到這種異常之後應該盡快退出執行。
在oc中,arc預設情況不是異常安全的,有可能是因為異常而產生嚴重的記憶體洩露。理論上來說,oc++ 中得arc是異常安全的。但是@autoreleasepool塊任然可能導致後台執行緒發生記憶體洩露。使用異常安全的arc會導致效能下降,這也是應該避免大量使用oc++的原因之一。在clang中,制定-fobjc-arc-exception 編譯標誌就可使用異常安全的arc。
MySql錯誤處理 錯誤處理的例子
有幾種錯誤處理的宣告形式 如果任何錯誤 不是 not found 設定 l error 為 1 後繼續執行 declare continue handler for sqlexception set l error 1 如果發生任何錯誤 不是 not found 執行 rollback和產生一條錯誤...
MySql錯誤處理(三) 錯誤處理的例子
mysql錯誤處理 三 錯誤處理的例子 有幾種錯誤處理的宣告形式 如果任何錯誤 不是 not found 設定 l error 為 1 後繼續執行 declare continue handler for sqlexception set l error 1 如果發生任何錯誤 不是 not foun...
PHP 錯誤處理
在 php 中,預設的錯誤處理很簡單。一條訊息會被傳送到瀏覽器,這條訊息帶有檔名 行號以及一條描述錯誤的訊息。在建立指令碼和 web 應用程式時,錯誤處理是乙個重要的部分。如果您的 缺少錯誤檢測編碼,那麼程式看上去很不專業,也為安全風險敞開了大門。本教程介紹了 php 中一些最為重要的錯誤檢測方法。...