iOS 錯誤處理 (一)

2021-06-17 17:00:07 字數 3872 閱讀 7221

錯誤處理恐怕是開發過程中最讓人難受的環節之一。在正常情況下讓程式的各部分都正常工作已經是比較困難的了,乙個好的應用應該在出錯時也有得體的表現。

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 中一些最為重要的錯誤檢測方法。...