RAII 很美好, 威力也很強大, 但一遇到 unix signal, 就沒轍了。
按下 Ctrl-C 之後, 解構函式不會發動, 這是很自然的, 因為 c++ 編譯器將解構函式安插在 39 那行, 而 Ctrl-C 按下後, 會執行 sig_handle, 不會在回到 39 那行, 自然無法發動解構函式。
RAII 破功? 雖然很不想承認, 但這是真的。c++ 神話破功了。
不過只要 a 是 global object, 那就沒問題, 解構函式還是會正常發動, 算是不幸中的大幸。
回到 local object 的版本, 那該怎麼辦? 如何讓 sig_handle 回到 39 那行呢?
我先是用了 exception handle, 但是失敗。
ref:
Throwing an exception from within a signal handler
24.9 Using a Separate Signal Stack
我推測可能是 sig_hanlde 發動的方式和一般函式呼叫不同, sig_handle 無法回到 main, 或是回到 main 但無法正確配對到 catch 的程式碼, signal handle 連 stack 都不同於這個程式。
使用了 gdb 來驗證看看, gdb 會攔截 sigint, 我改用 sigabort, sigabort 會傳給要除錯的那支程式, 得到
看起來好像是 main call sig_handle, 但實際上可能沒有這麼單純, 不管他了, 反正就是不能用 exception handle 處理這問題。換 exception handle 破功。
再用另外一招, 改用 setjmp/longjmp, 這就沒問題了, 解構函式正常發動。
結束了嗎? 還沒, 不要說 signal 這麼複雜的東西, exit 就可以讓 dtor 沒轍了。
A::~A() 不會發動呢! 那當然, 看看 r.dis, A::~A 根本沒被插到 main 裡頭, 能發動才有鬼。
按照慣例, 如果是 global object, 就算呼叫 exit, 依然可以正常發動 dtor。global object 是不是很好用呢?
至於為什麼 global object 可以正常發動 dtor, 不是什麼神奇的黑魔法, 在離開 main 之後, c++ runtime library 補了一段程式碼在 main 之後, 會把所有的 global/static object 的解構函式執行起來。
_exit 就不行了。
沒有留言:
張貼留言
使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。
我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。