2017-08-29 474 views
10

具體而言,我想知道GCC會如何確保在與使用-fno-exceptions編譯的代碼鏈接時如何引發異常行爲。當拋出異常的代碼與使用-fno-exceptions編譯的庫鏈接時會發生什麼?

GNU libstdc++說明書以下here

之前詳述-fno-exceptions庫的支持,首先在當使用該標誌失去的東西通過的紙幣:它會破壞異常試圖通過與-fno-exceptions編譯代碼,代碼是否有任何trycatch結構體。如果您可能會拋出一些代碼,則不應使用-fno-exceptions。如果您有一些使用trycatch的代碼,則不應使用-fno-exceptions

這聽起來像是一句話:「你不應該......」也就是說。未定義的行爲。

在另一方面,我從this SO question的印象是,一切都是猶太只要用-fno-exceptions編譯的代碼不throwtry,或catch(顯然是一個編譯時錯誤)和異常從未通過函數傳播從這個圖書館。這是有道理的:爲什麼圖書館編譯-fno-exceptions只要不與其功能交互就拋出異常?

我做了一些修補,發現如果我使用GCC 7.1.1編譯一個簡單的程序,其中一個源文件編譯爲-fno-exceptions,另一個引發並捕獲異常,則所有編譯,鏈接和運行都正常。但這並不意味着這種行爲是有保證的;它仍然可能是未定義的。

我的動機是,我有一種情況,我將自己的應用程序代碼與使用-fno-exceptions構建的庫鏈接起來,並根據對所述庫調用的函數調用,在我的即使該異常不通過庫的函數傳播,自己的代碼也會立即導致段錯誤。它聽起來像是圖書館裏的一個bug,但我認爲在編譯過程中通過-fno-exceptions時可以這樣做。

GCC的actual reference on code-generation flags提到-fexceptions相對簡短,並不回答我的問題。任何人都知道另一個參考/有相關經驗?

更新:我從源重建庫,這次打開異常支持。段錯誤依然存在!時間爲錯誤報告。

+3

我想說你認爲沒有明確聲明'-fno-exceptions'和'-fexceptions'是兼容的,但它是隱含的。然而(這裏有一個瘋狂的觀點),你確定你在拋出異常時沒有通過任何庫代碼。可能發生的顯而易見的'隱藏'方式是在堆棧展開中調用(或未調用或未命中)的'-fno-exceptions'析構函數。只是一個想法。 – Persixty

+2

我不認爲這就是我的情況,因爲即使我把'throw'直接放在'main'的'try' /'catch'中作爲測試,segfault仍然會出現。它永遠不允許傳播足夠多的觸發任何析構函數。當我讀到你的建議時,我只是做了一個雙倍的工作。我當然沒有想到這種可能性! –

+2

不客氣。只是拋出你的想法。我對gcc並不熟悉,當然也不是更奇特的配置。這些文檔肯定是這樣寫的:「這裏有一大堆的事情是爲了解決異常的問題。 – Persixty

回答

2

由於鏈接問題指出,GCC 需要允許-fno-exceptions-fexceptions爲了鏈接C和C++而共存。

從更理論上講,異常問題與程序的調用圖密切相關。這是一個有向圖(調用者/被調用者),但它可以是循環的,節點之間可以有多條邊。現在每個函數/節點都可以編譯,有或沒有例外。我們可以將一個安全程序定義爲一個程序,其中沒有「有例外」節點可以從「無例外」節點到達。

這可能是不必要的嚴格 - 在try...catch(...) { }塊內的C++位代碼應該可以從C代碼調用看起來是合理的。但我不知道GCC的保證。並考慮它的含義 - 調用圖與調用堆棧相關。調用堆棧通常形成從main()到當前正在執行的函數的路徑。如果整個路徑都是異常感知的,那麼異常是安全的。但是,如果有一個函數不知道異常,它可能會使堆棧處於一個不能安全處理異常的狀態,如果堆棧展開不會展開那麼遠,則可以使用甚至

相關問題