[英]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_error
與exception
相比具有其他數據成員,因此它會更改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.