c ++ std :: ios_base ::失败异常

时间:2016-08-23 12:44:39

标签: c++ linux c++11 exception iostream

标准(Dim NewClass As MyClass = PreviousClass(i) NewClass.Value1 = NewVal )说(N3337):

  

类失败定义了所有对象类型的基类   通过iostreams库中的函数作为异常抛出来报告   在流缓冲区操作期间检测到错误。

我有一个简单的测试程序,它在使用std :: ostringstream:

时模拟受限制的资源环境
27.5.3.1.1 Class ios_base::failure

在我的环境(Linux,gcc 5.3.0)中,我在#include <sys/time.h> #include <sys/resource.h> #include <errno.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <sstream> int main(int argc, const char* argv[]) { rlimit limit; limit.rlim_cur = limit.rlim_max = 268435456; if(setrlimit(RLIMIT_AS, &limit)) { std::cerr << "Cannot set resource limit: " << strerror(errno) << std::endl; exit(EXIT_FAILURE); } std::ostringstream os; os.exceptions(std::ostringstream::badbit); try { auto iterations = 1024 * 1024 * 1024; while(iterations && --iterations) os << 'F'; } catch(const std::ios_base::failure& ex) { std::cerr << "Caught: std::ios_base::failure" << std::endl; } catch(const std::bad_alloc& ex) { std::cerr << "Caught: std::bad_alloc" << std::endl; } catch(...) { std::cerr << "Caught: ellipsis" << std::endl; } return 0; } 上获得了Caught: std::bad_allocOne of online compilers显示相同的输出。

问题是:为什么例外类型为stderr而不是std::bad_alloc

2 个答案:

答案 0 :(得分:2)

os << 'F';operator<<(ostream&, char),这是格式化输出函数,引用27.7.3.6.1 [ostream.formatted.reqmts],

  

该函数努力生成请求的输出。如果生成失败,则格式化的输出函数执行setstate(ios_base::failbit),这可能会引发异常。如果在输出期间抛出异常,则会打开ios::badbit而不会导致ios::failure被抛出。在*this的错误状态。如果(exceptions()&badbit) != 0则重新抛出异常

作为输出的一部分,此函数调用在stringbuf::overflow中指定的27.8.2.4[stringbuf.virtuals]p8来执行重新分配。 libstdc ++和libc ++之间的区别在于对其分配失败的后果的解释:

在libstdc ++中,它从std::bad_alloc中抛出stringbuf::overflow,它将堆栈一直展开到operator<<(技术上,__ostream_insert),设置badbit并按上述规定重新投入,未经修改。

在libc ++中,std::bad_allocstringbuf::overflow捕获,并使overflow返回traits::eof,而steambuf::xsputn又会使调用方(在本例中为{{} 1}})返回零,这反过来使调用者__pad_and_output彻底消灭了流的rdbuf,这反过来使其调用者__put_character_sequence设置为badbit和failbit。设置该badbit会引发你抓到的ios::failure

也许libc ++在技术上是正确的stringbuf::overflow:标准说

  

&#39;&#39;返回:&#39;&#39; traits::eof()表示失败。

除了分配失败之外,很难想象它失败的方法,但我认为libstdc ++的解释更接近于意图。 (在libstdc ++中,stringbuf::overflow仍然可以返回eof,如果缓冲区容量达到string::max_size而没有首先点击bad_alloc

答案 1 :(得分:0)

您正在创建的错误情况不是由流缓冲区操作本身引起的错误。在某些时候,你只是耗尽了内存,流的分配器将抛出bad_alloc。这是你看到的例外。

bad_alloc是否应该作为ios_base :: failure重新引发是有争议的,因为最后,流操作确实失败了。在这种情况下,我看到bad_alloc的情况并不奇怪。