簡體   English   中英

沒有捕到異常使用C ++打開一個不存在的文件

[英]Exception not caught opening a non-existing file using C++

我從這里運行MWE: http ://www.cplusplus.com/reference/ios/ios/exceptions/在我的機器上它沒有捕獲異常。 這是我的代碼

#include <iostream>
#include <fstream>

int main()
{
    std::ifstream file;
    file.exceptions( std::ifstream::failbit | std::ifstream::badbit );
    try
    {
        file.open("IDoNotExist.txt");
    }
    catch(const std::ifstream::failure& e)
    {
        std::cout << "Bad luck!" << std::endl;
    }
}

在Arch-Linux上使用gcc 6.2.1我得到:

在拋出'std :: ios_base :: failure'的實例后終止調用

what():basic_ios :: clear

但是,在上面發布的鏈接中,提到代碼還應該捕獲與打開文件相關的異常。 什么地方出了錯?

它看起來像libstdc ++中已知錯誤

問題是隨着對C ++ 11 ABI的更改,許多類在libstdc++6.so中重復,一個版本使用舊版ABI,另一個版本使用舊版本。

異常類沒有重復,因此當時不存在這個問題。 但是,在一些新版本的語言中,決定std::ios_base::failure應該來自std::system_error而不是std::exception ...但是system_error只是一個C ++ 11類,所以它必須使用新的ABI標志或它會抱怨。 現在你有兩個不同的std::ios_base::failure類,手中有一個亂七八糟的東西!

簡單的解決方案是使用-D_GLIBCXX_USE_CXX11_ABI=0編譯程序並-D_GLIBCXX_USE_CXX11_ABI=0到舊的ABI,直到錯誤解決。 或者,寫catch (std::exception &e)

NB std::ifstream::failure在定義的類型std::ios_base基類ifstream ,所以這個答案的其余部分是指它作為std::ios_base::failure或只是std::ios::failure

這里的問題是,由於GCC 5在libstdc ++中有兩種不同的std::ios_base::failure定義(更多細節請參見Dual ABI文檔 )。 這是必要的,因為C ++ 11改變了ios::failure的定義:

class ios_base::failure : public exception {

至:

class ios_base::failure : public system_error {

這是一個ABI更改,因為system_errorexception相比具有其他數據成員,因此它會更改ios::failure的大小和布局。

因此,從GCC 5.1開始,當您的代碼名稱為std::ios_base::failure (或std::ifstream::failure或其他任何名稱)時,您獲得的定義取決於_GLIBCXX_USE_CXX11_ABI宏的值。 libstdc++.so庫中發生iostream錯誤時,拋出哪種類型取決於libstdc++.so時宏的值libstdc++.so構建了。 如果您嘗試捕獲一種類型並且庫拋出另一種類型,則catch將不起作用。 這就是你所看到的。 在你的代碼中, std::ifstream::failure命名新類型,但是庫拋出舊類型,這是一個不同的類,因此catch處理程序不匹配。

使用GCC 5.x和6.x libstdc++.so的代碼libstdc++.so拋出舊類型,所以為了捕獲它,你需要使用-D_GLIBCXX_USE_CXX11_ABI=0編譯代碼或將你的處理程序更改為catch (const std::exception&) (因為舊類型和新類型都來自std::exception )。

使用GCC 7.x,庫中的代碼拋出類型(由PR 66145更改),因此您需要使用-D_GLIBCXX_USE_CXX11_ABI=1或catch std::exception編譯代碼。

對於GCC 8.x,庫現在拋出一個異常類型,可以由舊類型新類型的處理程序捕獲(由PR 85222更改),因此您無需更改代碼。 它將Just Work™。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM