看板 C_and_CPP 關於我們 聯絡資訊
問題(Question): 除了使用STL或是第三方函式庫,我會特別注意需不需要catch例外以外,自己編寫 程式大多都還是用旗標或返回值的方式來處理錯誤,因為我對什麼情況下該使用例 外處理其實沒有什麼概念。 比方說書上在介紹例外處理的章節,大多都採用除0錯誤當成範例,但除0錯誤可 以藉由運算前檢查除數來避免,為什麼會特別為此定義一個例外呢?還有像是 fstream若開檔失敗,則是藉由檢查實例來偵測,為什麼不拋出std::system_error 來作為表示呢?因為沒辦法從中抓到一個明確的規律或依據,我不太懂得什麼樣 的場合或情境,使用例外處理而不是判斷旗標或返回值。 請問關於這部分是不是有什麼技巧或經驗可以請各位先進提點一下呢? 謝謝。 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 1.169.112.157 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1632756033.A.4F8.html
Schottky: 除以 0 會產生 interrupt 那跟 CPU 內的除法器設計有關 09/28 00:02
Schottky: 也有一些浮點除法器會直接除出無限大或 NaN 給你就結案 09/28 00:04
Schottky: 我自己寫 library 也不用例外機制而用傳回值表示 09/28 00:07
Schottky: 因為我希望他在 C 和 C++ 都能通用 09/28 00:07
Lipraxde: 你說的「例外處理」,指的是 C++ 的 exception,還是指 09/28 00:18
Lipraxde: 另外寫 code 處理?還有「例外」,是哪種類型的例外? 09/28 00:18
icetofux: 使用try、catch、throw語法的例外處理 09/28 07:13
ddavid: 對exception的態度其實人人不同,沒有統一規則 09/28 11:33
ddavid: 相對比較中庸的說法是你想得到的錯誤就直接檢查,想不到的 09/28 11:35
ddavid: 就留給例外去抓,但即便如此還是很模糊 09/28 11:35
ddavid: 比如硬碟壞軌,這是一種可以預想到的錯誤,但你不可能為了 09/28 11:36
ddavid: 想得到這個發生機率相對低的狀況,就在所有讀寫前面都加上 09/28 11:36
ddavid: 壞軌檢測過了才讀寫 09/28 11:36
ddavid: 另外就是有些語言根本已經把exception內化成一種流程控制 09/28 11:37
ddavid: 手段而非單單的錯誤處理,所以某些地方用起來只是另一種if 09/28 11:38
ddavid: ,而且「可能」寫起來比較簡單,這又是另一種狀況了 09/28 11:39
pponywong: 大哉問 我覺得是沒辦法回復的錯誤 用例外處理 09/28 13:00
pponywong: 剩下可以回復 或是可以回傳錯誤傳值給使用者的 09/28 13:01
pponywong: 用C的錯誤處理 這是我的習慣 也許別人不是這樣 09/28 13:01
ddavid: 我是比較不會用能否回復來做為區分,自己的基本概念是預防 09/28 14:20
ddavid: 與治療,你事先寫好的判斷就是預防它發生或者發生了也不會 09/28 14:20
ddavid: 造成問題,所以反而不會有恢復行為。比如事前判斷除以零會 09/28 14:22
ddavid: 出錯,所以提早發現0,直接不除,所以預防了事情直接發生 09/28 14:23
ddavid: 治療則是事情讓它發生了,事前沒有預料、或者就算預料到也 09/28 14:24
ddavid: 無法不讓它發生,所以只好讓它發生後做一些治療方案,看要 09/28 14:25
ddavid: 盡可能繼續跑或至少留些log再死 09/28 14:25
ddavid: 所以我的區分標準比較像是「你能否阻止它發生」 09/28 14:26
ddavid: 但是因為某些便利性或者語言特性(如Python),我其實也沒 09/28 14:27
ddavid: 這麼遵守這概念就是,還是很彈性去處理這問題XD 09/28 14:28
sarafciel: 某些語言第一個想到的就是那個J開頭的XD 09/28 15:30
ddavid: Python也是啊,連基本的for loop行為就是一直call 09/28 17:01
ddavid: next()直到iterator丟出StopIteration exception而中斷 09/28 17:02
ddavid: Python也有不少基本跟常用package根本上就完全使用例外來 09/28 17:04
ddavid: 回應所有正常完成以外的狀態,完全讓你被迫使用 09/28 17:06
ddavid: 我抱持上面講到的概念剛從C/C++轉而接觸到Python想說「靠 09/28 17:06
ddavid: ,怎麼滿地都是exception強迫使用啊?」結果現在也是用爽 09/28 17:07
ddavid: 爽了XD 09/28 17:07
a27417332: 我也有類似的疑惑,CppCon有類似的主題在說 09/28 19:34
a27417332: 我自己理解是對於pre/postcondition用類assert的機制 09/28 19:36
a27417332: 針對邏輯上的失敗,可以用expected這種方式 09/28 19:38
a27417332: 可能會發生但也不知道怎麼處理(OOM)的就用exception 09/28 19:39
a27417332: Herb有提議新的exception機制,感覺Rust做法和他很像 09/28 19:42
a27417332: 裡面提到因例外發生時效率差太多,所以社群主流都不使 09/28 19:47
a27417332: 用 09/28 19:47
a27417332: 前面說的針對邏輯上的失敗描述不太好,應該說像是開檔 09/28 19:52
a27417332: 或是把字串變成數字這種任務,通常不會希望因非法字串 09/28 19:52
a27417332: 就丟個例外讓人處理,因為業務邏輯上本身很有可能發生 09/28 19:52
ArdenCho: 可以使用 try catch 的語法來進行錯誤例外處理,會比 09/28 22:57
ArdenCho: 使用 if 還方便許多,而且有些狀況是完全沒辦法使用判 09/28 22:57
ArdenCho: 斷式來進行錯誤處理的。 但像您的狀況,也可以在執行 09/28 22:57
ArdenCho: 除法之前先檢查除數。 09/28 22:57
shibin: 我是寫utility很習慣會throw,卻不知道catch後怎麼處理好 09/28 23:25
shibin: 已檢查出某些狀況會導致後續動作無法正常執行 就可以throw 09/28 23:32
想延伸請教一個用例:假如我要存取一個未知長度std::vector中的某個元素,可以先使用size()確認元素位址是否合理再進行[]存取、也可以直接用at()存取當元素不存在會throw std::out_of_range,以語法長度來看其實兩者都差不多,但這是明顯可預期會發生的異常,例外處理的資源成本也比較多高,是否代表使用前者會比較合適呢? ※ 編輯: icetofux (111.71.102.71 臺灣), 09/29/2021 08:40:27
sarafciel: 一般是會用前者 不過理由跟你想探討的錯誤處理無關XD 09/29 12:38
longlongint: 我是寫android 程式才有感覺。可是這裡是C板XD 10/01 00:04
longlongint: 底層太抽象+錯誤資訊跟回傳值想分離的時候好用 10/01 00:05