2016-02-29 121 views
1

我试图捕获从main读取类方法中的文件时发生错误时引发的异常。简化的代码是这样的:主要捕获ifstream异常

#include <iostream> 
#include <fstream> 
#include <string> 

class A 
{ 
public: 
    A(const std::string filename) 
    { 
     std::ifstream file; 
     file.exceptions(std::ifstream::failbit | std::ifstream::badbit); 
     file.open(filename); 
    } 

}; 

int main() 
{ 
    std::string filename("file.txt"); 
    try 
    { 
     A MyClass(filename); 
    } 
    catch (std::ifstream::failure e) 
    { 
     std::cerr << "Error reading file" << std::endl; 
    } 

} 

我编译此代码:

$ g++ -std=c++11 main.cpp 

如果file.txt的存在没有任何反应,但是当它不,该计划有以下错误而终止:

terminate called after throwing an instance of 'std::ios_base::failure' 
    what(): basic_ios::clear 
zsh: abort (core dumped) ./a.out 

但我希望代码捕获异常并显示错误消息。为什么它没有捕捉到异常?

+0

哪个编译器版本?在这里工作很好。 –

+0

@Christian Hackl g ++ vresion 5.3.0 – Msegade

+3

@Msegade这是一个[GCC bug](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145)。 – LogicStuff

回答

2

通过在命令行中添加-D_GLIBCXX_USE_CXX11_ABI=0,可以使其在GCC中正常工作。 Here是GCC的一个工作示例。

从下面的评论(尤其是LogicStuff的测试)和我自己的测试中看来,在叮当声和MSVC中它不会产生这个错误。

感谢上面的LogicStuff的评论,我们现在知道这是一个GCC bug。因为在GCC C++ 03中ios :: failure不是从runtime_error派生的,所以没有被捕获。

另一种选择可能是更改为:

try 
{ 
    A MyClass(filename); 
} 
catch (std::ifstream::failure e) 
{ 
    std::cerr << "Error reading file\n"; 
} 
catch (...) 
{ 
    std::cerr << "Some other error\n"; 
} 
+0

不会崩溃[here](http://coliru.stacked-crooked.com/a/c52d4b1cce7814b8)。而'std :: ifstream :: failure'应该和'std :: ios_base :: failure'相同。它是继承的。 – LogicStuff

+2

'std :: ios_base :: failure'和'std :: ifstream :: failure'是*相同的*类型。 –

+2

由于'ifstream'中的'exceptions'是从'std :: basic_ios'继承的,它应该是相同类型 – NathanOliver