看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《volleyp (彼德さん)》之銘言: : 開發平台(Platform): (Ex: VC++, GCC, Linux, ...) : 想請問在處理錯誤的時候,會怎麼選擇用throw還是return false ? : 最近在看資料結構的書,裡面的程式碼在判斷式的地方好像都是用throw來處理不合條件 : 的情況。但之前我看其他人寫遊戲的時候會用return false來做處理。蠻好奇這兩種 : 做法的差異在哪邊!麻煩前輩們指教一下,謝謝! 個人是不推薦Exception派的 C++雖然有Exception 但是使用上卻很難安全使用 有幾個問題應該可以提出來討論看看 也許只是我功力還不夠 首先是資源釋放問題 C++沒有GC! 發生例外的時候 會跳出try的區域到catch去 如果沒有使用shared_ptr 那麼成功配置的資源將會無法釋放 因為已經拿不到那些local指標 這不只發生在函數內部 物件創立時也可能發生 比方說配置物件後方的member data時 發生要不到記憶體而丟出例外 建構失敗之後就不會執行解構 結果前面的配置空間就會發生memory leak 這個方面可以參考書籍Efficient C++ 不過我覺得不是每個人都會讀過這本書 再來是程式可讀性 return error code的方式 可以很容易就看出程式撰寫時已經考慮哪些問題 throw exception並不容易看出程式是否思考仔細 而且顯然與別人合作寫程式的時候 需要大家先規範好要丟出什麼樣的東西 用error code反而簡單很多,寫個enum或是define就好 只傳遞問題敘述,但是函數內部的問題,由該函數自己處理 這樣程式會比較內斂一點 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.113.210.62
jackace:推這篇 04/12 13:26
另外還有一點要補充的 例外機制很難在程式中後期加入 這不能靠重構解決問題 不是資料封裝性的事情而已 還直接影響程式運行邏輯 要就只能在初期就考慮周詳 不然就乾脆不要使用 ※ 編輯: iamstudent 來自: 140.113.210.62 (04/12 13:42)
littleshan: #1A8WRrhc 04/12 14:31
littleshan:另外ctor沒有回傳值,若再考慮有繼承的情況 04/12 14:32
littleshan:其實很難用error code做處理 04/12 14:32
iamstudent:construtor我沒話說,沒辦法用error code 04/12 14:47
iamstudent:至於一般函數我覺得還是看不出exception好處 04/12 14:49
iamstudent:底層無法處理,丟到外層就能處理的情況,我只想到缺RAM 04/12 14:50
iamstudent:一般出錯了,就近解決問題應該比較容易才對吧 04/12 14:52
iamstudent:不然外層要知道的細節未免也太多了 04/12 14:53
littleshan:簡單情境:發生錯誤時要寫到log還是直接MessageBox 04/12 14:53
littleshan:這個只有外面知道要怎麼做 04/12 14:54
※ 編輯: iamstudent 來自: 140.113.210.62 (04/12 14:54)
iamstudent:需要統一管理處理方式的時候需要這樣作嗎? 04/12 14:56
littleshan:寫library給別人用的時候你不知道他要怎麼處理啊 04/12 15:00
littleshan:另外error code占用回傳值,原本回傳值只能用ref參數 04/12 15:02
littleshan:這很麻煩,寫到最後覺得自己根本在寫assembly 04/12 15:03
謝謝,這樣我就理解了 我原本的角度是函數撰寫者與使用者都是自己人的情況 所以忽略了撰寫library的情形 由於函數傳回值只有一個 改用ref參數傳回error code 那麼函數的介面會變很醜 看了你推薦的那篇文章之後還瞭解一點 使用error code方式處理 每次呼叫都要作的檢查 會出現很多check處理 我目前有碰過一些C的library 作法是有額外的Check函數 可以在一連串動作之後才檢查error code 而不是每個動作都檢查 也不需要在每個函數上面多出ref傳遞錯誤代碼 函數的參數就可以很乾淨 這樣應該也是一個解法 此外Constructor也有解法 就是Constructor放空 然後多一個Init的成員函數 使用者必須手動初始化 會placement new的人可能覺得很多餘 可是這樣其實很容易被理解 獨立初始化就可以輕易處理error code 不過這樣要配合stl容器就有點頭痛了 裡面有copy constructor...
amozartea:推這篇, throw一整個很難處理記憶體問題... 04/12 15:20
amozartea:不過反正還在開發階段時leak就讓他leak算了... 04/12 15:21
※ 編輯: iamstudent 來自: 140.113.210.62 (04/12 15:33)
Chikei:http://goo.gl/9KqRk 04/12 15:32
hilorrk:看到 exception 就要先想到 RAII,然後我的頭就痛了... 04/12 15:50
littleshan:Chikei 那篇滿中肯的 04/12 17:45
littleshan:exception和leak沒有絕對關係,用error code也可能leak 04/12 17:46
littleshan:error code的場合若不用RAII,是會寫出世界奇觀的 04/12 17:47
Ebergies:Exception 的程式明明比較簡單易懂... =.= 04/12 17:48
Ebergies:不過 C++ 用 Exception 比較麻煩是真的 04/12 17:49
Ebergies:Exception 的發明本身就是經過許多有經驗的前人為了解決 04/12 17:50
Ebergies:error code 造成的混亂才發明的東西 04/12 17:50
azureblaze:剛學directx之類的碰到一堆error check真的很想死XD 04/12 18:11
azureblaze:所以有些教學一開始會先忽略掉error check 04/12 18:12
azureblaze:然後之後開始error的時候就很想死 04/12 18:12
purpose:微軟在 CRT 原始碼裡面 (純C語言),沒有 RAII 可以用 04/12 19:03
purpose:都用 goto 解決。改用 while() 再 break 避開 goto 也行啦 04/12 19:04
iamstudent:littleshan的說法好像是對的,error code不搭配RAII 04/12 19:14
iamstudent:感覺是建立在new或malloc都不會出問題的假設上 04/12 19:15
iamstudent:只有錯誤與配置資源無關時才能不用RAII的樣子 04/12 19:17
hpps:linux原始碼大量使用error code跟goto,看得很累 04/12 22:33
yoco315:leak跟except是正交的問題,modern c++ 已經完全不推薦自己 04/13 12:29
yoco315:用 raw pointer 管理資源,而且這個轉化跟 exception 無關 04/13 12:30
yoco315:單純只是手動管理太容易出錯,能用 container 的就用contnr 04/13 12:30
yoco315:該用 shared 的就 shared,該 scope/unique 就 scope/uniq 04/13 12:31
yoco315:弄清每個資源的所有權跟生命週期的種類應該是哪種… 04/13 12:34
yoco315:以用正確的包裝,以求最高效能最小的心智負擔才是C++ style 04/13 12:35