您好,登錄后才能下訂單哦!
我們之前學習了異常有關的知識,那么如果在 main 函數中中拋出異常會發生什么呢?如果異常不進行處理,最后會傳到哪里呢?如下
下來我們就來做個實驗,代碼如下
#include <iostream> using namespace std; class Test { public: Test() { cout << "Test()" << endl; } ~Test() { cout << "~Test()" << endl; } }; int main() { static Test t; throw 1; return 0; }
我們先來看看 g++ 編譯器是怎樣處理的
我們看到在打印了構造函數的語句之后,下面還輸出兩句話,那么我們并沒有在程序中定義這樣的輸出啊,這個到底是誰打印出來的呢?我們來看看 BCC 編譯器
在 BCC 編譯器中輸出了下面的一句話,也并不是我們定義的。我們再來看看 vs2010 編譯器
我們看到在 vs2010 編譯器中彈出了一個對話框,我們并沒有編寫相關的代碼。我們來看看編譯器在背后究竟做了哪些事,如果異常無法被處理,terminate() 結束函數會被自動調用。默認情況下,terminate() 調用庫函數 abort() 終止程序,abort() 函數使得程序執行異常而立即退出,C++ 支持替換默認的 terminate() 函數實現。
terminate() 函數的替換:a> 它是自定義一個無返回值無參數的函數,不能拋出任何異常,必須以某種方式結束當前程序;b> 調用 set_terminate() 設置自定義的結束函數,參數類型為 void(*)(),返回值為默認的 terminate() 函數入口地址。
下來我們來自定義 terminate() 函數。
#include <iostream> #include <cstdlib> #include <exception> using namespace std; void my_terminate() { cout << "void my_terminate()" << endl; exit(1); } class Test { public: Test() { cout << "Test()" << endl; } ~Test() { cout << "~Test()" << endl; } }; int main() { set_terminate(my_terminate); static Test t; throw 1; return 0; }
我們再來看看編譯結果,先在 g++ 編譯器下
我們看到程序正常運行結束了。我們來分析下,我們在 main 函數中調用 set_terminate() 設置結束函數 my_terminate()。在 main 函數中拋出了一個異常,被結束函數 my_terminate() 捕獲到了,然后執行它里面的打印語句,進而執行到 exit(1) 正常退出。所以在最后退出的時候會去執行析構函數。我們再來看看 BCC 編譯器呢
我們看到和 g++ 編譯器中的行為是一樣的,再來看看 vs2010 編譯器看看
那么如果在析構函數中拋出異常會發生什么情況呢?我們來試試,在上面的程序中的析構函數拋出一個異常,看看編譯結果
我們看到最后又去調用內置的 Aborted 函數了。再來看看 BCC 編譯器呢
同樣也是這樣的情況,看看 vs2010 編譯器
我們來分析下,它先是在 main 函數中拋出異常,然后執行到 my_terminate() 函數中,進而退出(清理一切資源等),在退出的時候又去執行析構函數,又再次拋出異常,等于又要再次進行資源的釋放,造成二次釋放了。類似于在操作指針時,二次釋放,所帶來的后果是無法確定的。因此它最后會去調用庫函數中的 abort() 函數。因此,我們在 main 函數中盡量不要拋出異常。通過對異常的深度學習,總結如下:1、如果異常沒有被處理,最后 terminate() 結束整個程序;2、terminate() 是整個程序釋放系統資源的最后機會;3、結束函數可以自定義,但不能繼續拋出異常;4、析構函數中不能拋出異常,可能導致 terminate() 多次調用。
歡迎大家一起來學習 C++ 語言,可以加我QQ:243343083。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。