[問題] 什麼樣的"錯誤"該用例外處理

看板C_and_CPP (C/C++)作者時間3年前 (2021/09/27 23:20), 3年前編輯推噓8(8048)
留言56則, 10人參與, 3年前最新討論串1/2 (看更多)
問題(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

09/28 00:02, 3年前 , 1F
除以 0 會產生 interrupt 那跟 CPU 內的除法器設計有關
09/28 00:02, 1F

09/28 00:04, 3年前 , 2F
也有一些浮點除法器會直接除出無限大或 NaN 給你就結案
09/28 00:04, 2F

09/28 00:07, 3年前 , 3F
我自己寫 library 也不用例外機制而用傳回值表示
09/28 00:07, 3F

09/28 00:07, 3年前 , 4F
因為我希望他在 C 和 C++ 都能通用
09/28 00:07, 4F

09/28 00:18, 3年前 , 5F
你說的「例外處理」,指的是 C++ 的 exception,還是指
09/28 00:18, 5F

09/28 00:18, 3年前 , 6F
另外寫 code 處理?還有「例外」,是哪種類型的例外?
09/28 00:18, 6F

09/28 07:13, 3年前 , 7F
使用try、catch、throw語法的例外處理
09/28 07:13, 7F

09/28 11:33, 3年前 , 8F
對exception的態度其實人人不同,沒有統一規則
09/28 11:33, 8F

09/28 11:35, 3年前 , 9F
相對比較中庸的說法是你想得到的錯誤就直接檢查,想不到的
09/28 11:35, 9F

09/28 11:35, 3年前 , 10F
就留給例外去抓,但即便如此還是很模糊
09/28 11:35, 10F

09/28 11:36, 3年前 , 11F
比如硬碟壞軌,這是一種可以預想到的錯誤,但你不可能為了
09/28 11:36, 11F

09/28 11:36, 3年前 , 12F
想得到這個發生機率相對低的狀況,就在所有讀寫前面都加上
09/28 11:36, 12F

09/28 11:36, 3年前 , 13F
壞軌檢測過了才讀寫
09/28 11:36, 13F

09/28 11:37, 3年前 , 14F
另外就是有些語言根本已經把exception內化成一種流程控制
09/28 11:37, 14F

09/28 11:38, 3年前 , 15F
手段而非單單的錯誤處理,所以某些地方用起來只是另一種if
09/28 11:38, 15F

09/28 11:39, 3年前 , 16F
,而且「可能」寫起來比較簡單,這又是另一種狀況了
09/28 11:39, 16F

09/28 13:00, 3年前 , 17F
大哉問 我覺得是沒辦法回復的錯誤 用例外處理
09/28 13:00, 17F

09/28 13:01, 3年前 , 18F
剩下可以回復 或是可以回傳錯誤傳值給使用者的
09/28 13:01, 18F

09/28 13:01, 3年前 , 19F
用C的錯誤處理 這是我的習慣 也許別人不是這樣
09/28 13:01, 19F

09/28 14:20, 3年前 , 20F
我是比較不會用能否回復來做為區分,自己的基本概念是預防
09/28 14:20, 20F

09/28 14:20, 3年前 , 21F
與治療,你事先寫好的判斷就是預防它發生或者發生了也不會
09/28 14:20, 21F

09/28 14:22, 3年前 , 22F
造成問題,所以反而不會有恢復行為。比如事前判斷除以零會
09/28 14:22, 22F

09/28 14:23, 3年前 , 23F
出錯,所以提早發現0,直接不除,所以預防了事情直接發生
09/28 14:23, 23F

09/28 14:24, 3年前 , 24F
治療則是事情讓它發生了,事前沒有預料、或者就算預料到也
09/28 14:24, 24F

09/28 14:25, 3年前 , 25F
無法不讓它發生,所以只好讓它發生後做一些治療方案,看要
09/28 14:25, 25F

09/28 14:25, 3年前 , 26F
盡可能繼續跑或至少留些log再死
09/28 14:25, 26F

09/28 14:26, 3年前 , 27F
所以我的區分標準比較像是「你能否阻止它發生」
09/28 14:26, 27F

09/28 14:27, 3年前 , 28F
但是因為某些便利性或者語言特性(如Python),我其實也沒
09/28 14:27, 28F

09/28 14:28, 3年前 , 29F
這麼遵守這概念就是,還是很彈性去處理這問題XD
09/28 14:28, 29F

09/28 15:30, 3年前 , 30F
某些語言第一個想到的就是那個J開頭的XD
09/28 15:30, 30F

09/28 17:01, 3年前 , 31F
Python也是啊,連基本的for loop行為就是一直call
09/28 17:01, 31F

09/28 17:02, 3年前 , 32F
next()直到iterator丟出StopIteration exception而中斷
09/28 17:02, 32F

09/28 17:04, 3年前 , 33F
Python也有不少基本跟常用package根本上就完全使用例外來
09/28 17:04, 33F

09/28 17:06, 3年前 , 34F
回應所有正常完成以外的狀態,完全讓你被迫使用
09/28 17:06, 34F

09/28 17:06, 3年前 , 35F
我抱持上面講到的概念剛從C/C++轉而接觸到Python想說「靠
09/28 17:06, 35F

09/28 17:07, 3年前 , 36F
,怎麼滿地都是exception強迫使用啊?」結果現在也是用爽
09/28 17:07, 36F

09/28 17:07, 3年前 , 37F
爽了XD
09/28 17:07, 37F

09/28 19:34, 3年前 , 38F
我也有類似的疑惑,CppCon有類似的主題在說
09/28 19:34, 38F

09/28 19:36, 3年前 , 39F
我自己理解是對於pre/postcondition用類assert的機制
09/28 19:36, 39F

09/28 19:38, 3年前 , 40F
針對邏輯上的失敗,可以用expected這種方式
09/28 19:38, 40F

09/28 19:39, 3年前 , 41F
可能會發生但也不知道怎麼處理(OOM)的就用exception
09/28 19:39, 41F

09/28 19:42, 3年前 , 42F
Herb有提議新的exception機制,感覺Rust做法和他很像
09/28 19:42, 42F

09/28 19:47, 3年前 , 43F
裡面提到因例外發生時效率差太多,所以社群主流都不使
09/28 19:47, 43F

09/28 19:47, 3年前 , 44F
09/28 19:47, 44F

09/28 19:52, 3年前 , 45F
前面說的針對邏輯上的失敗描述不太好,應該說像是開檔
09/28 19:52, 45F

09/28 19:52, 3年前 , 46F
或是把字串變成數字這種任務,通常不會希望因非法字串
09/28 19:52, 46F

09/28 19:52, 3年前 , 47F
就丟個例外讓人處理,因為業務邏輯上本身很有可能發生
09/28 19:52, 47F

09/28 22:57, 3年前 , 48F
可以使用 try catch 的語法來進行錯誤例外處理,會比
09/28 22:57, 48F

09/28 22:57, 3年前 , 49F
使用 if 還方便許多,而且有些狀況是完全沒辦法使用判
09/28 22:57, 49F

09/28 22:57, 3年前 , 50F
斷式來進行錯誤處理的。 但像您的狀況,也可以在執行
09/28 22:57, 50F

09/28 22:57, 3年前 , 51F
除法之前先檢查除數。
09/28 22:57, 51F

09/28 23:25, 3年前 , 52F
我是寫utility很習慣會throw,卻不知道catch後怎麼處理好
09/28 23:25, 52F

09/28 23:32, 3年前 , 53F
已檢查出某些狀況會導致後續動作無法正常執行 就可以throw
09/28 23:32, 53F
想延伸請教一個用例:假如我要存取一個未知長度std::vector中的某個元素,可以先使用size()確認元素位址是否合理再進行[]存取、也可以直接用at()存取當元素不存在會throw std::out_of_range,以語法長度來看其實兩者都差不多,但這是明顯可預期會發生的異常,例外處理的資源成本也比較多高,是否代表使用前者會比較合適呢? ※ 編輯: icetofux (111.71.102.71 臺灣), 09/29/2021 08:40:27

09/29 12:38, 3年前 , 54F
一般是會用前者 不過理由跟你想探討的錯誤處理無關XD
09/29 12:38, 54F

10/01 00:04, 3年前 , 55F
我是寫android 程式才有感覺。可是這裡是C板XD
10/01 00:04, 55F

10/01 00:05, 3年前 , 56F
底層太抽象+錯誤資訊跟回傳值想分離的時候好用
10/01 00:05, 56F
文章代碼(AID): #1XKU51Ju (C_and_CPP)
文章代碼(AID): #1XKU51Ju (C_and_CPP)