标准(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_alloc
。 One of online compilers显示相同的输出。
问题是:为什么例外类型为stderr
而不是std::bad_alloc
?
答案 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_alloc
被stringbuf::overflow
捕获,并使overflow
返回traits::eof
,而steambuf::xsputn
又会使调用方(在本例中为{{} 1}})返回零,这反过来使调用者__pad_and_output
彻底消灭了流的rdbuf,这反过来使其调用者__put_character_sequence
设置为badbit和failbit。设置该badbit会引发你抓到的ios::failure
。
也许libc ++在技术上是正确的stringbuf::overflow
:标准说
除了分配失败之外,很难想象它失败的方法,但我认为libstdc ++的解释更接近于意图。 (在libstdc ++中,&#39;&#39;返回:&#39;&#39;
traits::eof()
表示失败。
stringbuf::overflow
仍然可以返回eof
,如果缓冲区容量达到string::max_size
而没有首先点击bad_alloc
)
答案 1 :(得分:0)
您正在创建的错误情况不是由流缓冲区操作本身引起的错误。在某些时候,你只是耗尽了内存,流的分配器将抛出bad_alloc
。这是你看到的例外。
bad_alloc
是否应该作为ios_base :: failure重新引发是有争议的,因为最后,流操作确实失败了。在这种情况下,我看到bad_alloc
的情况并不奇怪。