[問題] 純C下的異常處理

作者: icetofux   2019-11-25 00:19:03
開發平台(Platform): (Ex: Win10, Linux, ...)

編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出)

額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)

問題(Question):
因為工作上的限制,我目前都在純C下進行程式開發,編譯器可相容於C99。
最近錯誤處理的問題讓我十分在意,一直在想有沒有辦法可以處理得更好、更為簡潔
所以想向各位先進請益。另外這問題其實不算是C/C++專有的問題,但考量到各語言
有不同的語法、處理技巧,我尤其希望能得到C語言上的解答,所以貼在這個版,若
版主覺得不適合或還是覺得有違板規,我會再進行修正或刪除。
用個簡單的範例來說明,我設計一個程式,當使用者點下按鈕時,將系統目前的日期
時間透過通訊發送給遠端設備,我將程式拆分為三個部分:
業務邏輯層->協議處理層->硬體驅動層
業務邏輯處理一些程式運作的主流程:當使用者按下UI上的按鈕,會取得目前系統時
間,並呼叫協議處理層提供的發送函式(比方說SendTime(...))。
協議處理層負責將收到的時間轉換為特定的編碼方式,比方說將年、月、日、時、分
、秒各自轉換為長度1-byte的資料,並依序排列成一個陣列,接著呼叫硬體驅動層提
供的發送函式(比如說SendData(...))。
硬體驅動實際處理了將資料發送出去的底層行為,這部分大多是呼叫系統提供的底層
API,或是在沒有OS的情況下直接進行暫存器操作。
我的問題在於,假設這三層所提供的函式中,都會有失敗的風險,最常見到的處理方
式就是在每個函式都加個回傳值來確認執行結果,比方說成功傳True、失敗傳False,
或是成功傳0、失敗有個return code之類的。這裡產生幾個我覺得疑惑的地方:
1.每次呼叫函式時都要加個if檢查式,寫到後面發現檢查跟業務邏輯用的code數量幾
乎是1:1,閱讀code時總會覺得業務邏輯跟檢查邏輯混在一起有點難閱讀,請問這
只需要去適應就好,好是有更好的方式可以處理呢?
2.我在三個層失敗的時候都會留下log,可是每當發生錯誤時回去讀log總覺得很冗餘
,比方說一但有個硬體異常引起的錯誤,我會在log中依序看到硬體驅動層的錯誤訊
息、協議處理層的錯誤訊息、業務邏輯層的錯誤訊息。但其實仔細想想硬體驅動層
一但失敗其他兩個層根本不可能會成功,這增加除錯時閱讀的難度,而且實質上浪
費了系統資源(記憶體、儲存媒體空間之類的),請問這部分有更好的取捨方式嗎?
我不確定有沒有把自己疑惑的地方好好表達清楚,如果有語意不明的地方請讓我知道。
謝謝。
餵入的資料(Input):

預期的正確結果(Expected Output):

錯誤結果(Wrong Output):

程式碼(Code):(請善用置底文網頁, 記得排版,禁止使用圖檔)

補充說明(Supplement):
作者: Schottky (順風相送)   2019-11-25 00:51:00
這是個很值得探討的問題,但我這陣子暫時沒空回文細說C 沒有 try-catch 因此錯誤處理確實要自己做不少事第一個問題可以用 macro 包裝固定的錯誤檢查程序第二個沒問題,其實出錯時你會想知道 call stack底層出錯時偶爾會想知道上層是哪隻豬居然這樣呼叫如果要集縮成一行也可以,就把錯誤訊息一路往上傳到最上層(你這邊是業務邏輯層)才寫log,每一層再各自加上自己的姓名和見解,就形成了一個完整的 call stack
作者: Ryspon (Ry)   2019-11-25 02:08:00
好奇推
作者: CodingMan (程式俠)   2019-11-25 08:44:00
我也想知道
作者: chuegou (chuegou)   2019-11-25 09:35:00
關注
作者: F04E (Fujitsu)   2019-11-25 10:10:00
我自己實務上也是採用Schottky的作法
作者: flysonics (飛音)   2019-11-25 11:07:00
和Schottky相似+1不過我的習慣是寫一個handler去接所有檢查邏輯fail的情況 這樣順帶可以從handler function下列清單 一目了然看到自己埋了哪些檢查點log的部分 我是會整個Task全部用一個structure去管萬一底層發生問題時 只要直接將必要資訊記在structure上 到最上層時再assert卡下來沒有try&catch 就自己兜個堪用的方便debug的概念
作者: Qbsuran (Qbsuran)   2019-11-25 15:46:00
wireshark有實作出try-catch(純C) 可以看看source
作者: eye5002003 (下一夜)   2019-11-25 18:21:00
我很懶惰,所以都是抓__FILE__跟__LINE__噴一下位置出問題的時候才來認真嵌訊息調查
作者: alan23273850   2019-11-26 10:31:00
我怎麼記得c++有支援try-catch
作者: ko27tye (好滋好滋)   2019-11-26 14:27:00
c++有阿 標題問的是C
作者: x246libra (楓)   2019-11-28 20:44:00
go的錯誤處理跟C有點像似 要參考一下嗎https://juejin.im/post/5d772620e51d4561c83e7cd2跳到 Opaque errors 來看
作者: exeex (執行檔EX)   2019-12-01 14:12:00
做起來應該跟golang有87%像不過golang可以return兩個以上的變數包含err, C要另外想辦法用macro把return包住是一個方法
作者: flysonics (飛音)   2019-12-02 15:24:00
用macro把return包住 這樣會讓後面讀code的人困擾吧...你包了個一格洞在裡面誰知道
作者: dou0228 (7777)   2019-12-05 17:10:00
wireshark exception + zlog, 不要用 __FILE__

Links booklink

Contact Us: admin [ a t ] ucptt.com