2011年11月19日 星期六

C++ 建構式和解構式使用 exception 的注意事項

item 08: Prevent exceptions from leaving destructor

一樣是要避免未定義行為, 清資源清到一半卻因 exception 而沒做完, 是不道德的, 有機會造成更多 memory leak。

《[17.9] How can I handle a destructor that fails?》指出更嚴重的問題, 當 exception A 發生時, C++ 不會執行剩下的程式, 而會跳到 catch A 的部份。但跳到 catch 前, 要先清掉這之中的 call stack, 自然會觸發各 function call 的 local variable 的 destructor。若在這時又丟出 exception B, 沒辦法決定該執行 catch A, 還是跳去執行 catch B。忠孝兩難全, 只好要求 process 自盡結束它短暫的一生。

所以說有 destructor 也不是都是好事, 像 Python / Java 沒法和你保證什麼時候會呼叫 "destructor" ( Python 的 __del__、Java 的 finalizer ), 自然不用擔心有這種 exception 中的 exception 兩難。只會另外建議你不要用 "destructor"

書中另外建議, 若想兼顧「自動回收資源」 (環保做功德) 和「避免在 destructor 內吞掉 exception」, 可另外提供方法讓使用者可呼叫函式清資源, 再自行處理可能丟出的 exception (像關 db connection)。若使用者忘了呼叫這類方法, destructor 再做最低限度的保護, 幫忙呼叫該函式清資源。不過有 exception 時, 使用者也沒得抱怨 destructor 吞掉 exception 沒處理。

那 constructor 內可不可以丟出 exception?

照理說要能丟比較何理, 不然怎麼處理 invalid argument? 查一下 FAQ, 果然有令人愉快的答案:

結論是不會有 memory leak, 也不會呼叫 destructor, 可以安心地丟 exception 出來。

沒有留言:

張貼留言

在 Fedora 下裝 id-utils

Fedora 似乎因為執行檔撞名,而沒有提供 id-utils 的套件 ,但這是使用 gj 的必要套件,只好自己編。從官網抓好 tarball ,解開來編譯 (./configure && make)就是了。 但編譯後會遇到錯誤: ./stdio.h:10...