c++std::ios_base::失败异常
c++ std::ios_base::failure exception
标准(N3337
(表示(27.5.3.1.1 Class ios_base::failure
(:
类失败定义了所有对象类型的基类iostreams库中的函数作为异常抛出以报告在流缓冲区操作期间检测到错误。
我有一个简单的测试程序,它在使用std::ostringstream:时模拟受限制的资源环境
#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;
}
在我的环境(Linux,gcc 5.3.0(中,我在stderr
上获得了Caught: std::bad_alloc
。其中一个在线编译器显示了相同的输出。
问题是:为什么异常类型是std::bad_alloc
而不是std::ios_base::failure
?
os << 'F';
是operator<<(ostream&, char)
,它是一个格式化输出函数,引用27.7.3.6.1[ostream.Formatted.rekmts],
该函数努力生成所请求的输出。如果生成失败,则格式化的输出函数执行
setstate(ios_base::failbit)
,这可能会引发异常。如果在输出过程中引发异常,则ios::badbit
将被打开,而不会引发ios::failure
。处于*this
的错误状态。如果是(exceptions()&badbit) != 0
,则异常为重新引发
作为输出的一部分,此函数调用27.8.2.4[stringbuf.virtuals]p8
中指定的stringbuf::overflow
来执行重新分配。libstdc++和libc++之间的区别在于对其分配失败后果的解释:
在libstdc++中,它将std::bad_alloc
从stringbuf::overflow
中抛出,CCD_17将堆栈一直展开到operator<<
(从技术上讲,是__ostream_insert
(,设置badbit
,然后重新抛出(未修改(,如上所述。
在libc++中,std::bad_alloc
被捕获在stringbuf::overflow
中,它使overflow
返回traits::eof
,这反过来又使调用方(在本例中为steambuf::xsputn
(返回零,这反过来使调用方__pad_and_output
完全清除流的rdbuf,这反过来也使其调用方CCD27设置坏比特和故障比特。设置该坏比特会抛出您捕获的ios::failure
。
也许libc++在stringbuf::overflow
中在技术上是正确的:标准上说
''返回:''
traits::eof()
表示失败。
除了分配失败之外,很难想象它会失败,但我认为libstdc++的解释更接近意图。(在libstdc++中,如果缓冲区容量达到string::max_size
而不首先命中bad_alloc
,则stringbuf::overflow
仍然可以返回eof
(
您正在创建的错误情况本身并不是由流缓冲区操作引起的错误。在某个时刻,您只是耗尽了内存,流的分配器将抛出一个bad_alloc
。这是你看到的例外。
bad_alloc
是否应该作为ios_base::failure重新抛出是有争议的,因为最终流操作确实会失败。不过,在这种情况下看到bad_alloc
的情况,我并不感到惊讶。
- 为什么此代码导致未处理的异常失败
- 使用双LL在C++中实现Stack失败,出现异常"EXC_BAD_ACCESS(代码=2,地址=0x7fff5
- 如何在使用 CFileDialog 打开文件失败时捕获异常
- 声纳库贝分析在 Eclipse 中失败,由于找不到异常语言"cpp"在本地分析中抛出错误
- 运行失败,没有任何异常
- 如何处理失败的方法:通过使用异常或使方法返回bool
- 捕获派生异常类型在 Clang/MacOS X 上失败
- 'new'语句是否可以在不引发异常的情况下失败?
- C++ 面向对象的编程异常失败
- vHRESULT 中未处理的异常失败
- C++自做异常处理失败
- 单元测试失败,异常代码为c0000005
- 异常类使用递归函数失败
- 程序在Turbo C中运行良好,但在MSVC中失败,出现未处理的异常
- 可能失败的函数的接收参数和移动语义(强异常安全性)
- 如何检查禁用异常的构造函数的失败
- 捕获异常:error: svd()收敛失败
- 试图在递归函数内部捕获失败的分配:未处理的异常/堆栈溢出
- c++异常处理失败
- c++std::ios_base::失败异常