gpt4 book ai didi

c++ - iostream 上的异常

转载 作者:可可西里 更新时间:2023-11-01 17:49:17 24 4
gpt4 key购买 nike

我最近了解到可以选择加入 iostream 的异常(exception)。为了不必手动检查文件是否打开,我试过了并遇到了这种行为:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>

void test(std::istream& is, bool exceptions) {
try {
if (exceptions)
is.exceptions(std::istream::failbit);
std::vector<int> input;
std::copy(std::istream_iterator<int>{is}, {}, std::back_inserter(input));
for (auto x : input) {
std::cout << x << '\n';
}
}
catch (const std::ios_base::failure& f) {
std::cerr << "Caught error: " << f.what() << '\n';
}
}

int main() {
// Emulates file
std::stringstream ss("1 2 3\n4 5 6\n7 8 9\n");
test(ss, true);
}

当异常被触发时,这会正常工作。但是当我使用异常时,我从 basic_ios::clear 中抛出了一个异常,我想不出原因。

basic_ios::clear 没有列在根据cppreference 可以设置failbit 的函数下.

提前致谢。

编辑: 下面的答案已经回答了为什么会发生这种情况。我现在的附加问题是如何避免这种异常?我的第二次尝试是用这个循环替换 std::copy:

for (int n; is >> n;) {
input.push_back(n);
}

产生了同样的异常。还是这种行为是有意为之的?

注意:clang 不会显示此行为。

最佳答案

使用 GDB,您可以看到当 std::istream_iterator 递增时发生错误。

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007ffff71d13fa in __GI_abort () at abort.c:89
#2 0x00007ffff7ae80ad in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007ffff7ae6066 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007ffff7ae60b1 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007ffff7ae62c9 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007ffff7b0eea3 in std::__throw_ios_failure(char const*) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007ffff7b4a82d in std::basic_ios<char, std::char_traits<char> >::clear(std::_Ios_Iostate) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#8 0x00007ffff7b4d52f in std::istream::operator>>(int&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9 0x00005555555556c2 in std::istream_iterator<int, char, std::char_traits<char>, long>::_M_read (this=0x7fffffffe230) at /usr/include/c++/6/bits/stream_iterator.h:121
#10 0x0000555555555ac2 in std::istream_iterator<int, char, std::char_traits<char>, long>::operator++ (this=0x7fffffffe230) at /usr/include/c++/6/bits/stream_iterator.h:95
#11 0x0000555555555a36 in std::__copy_move<false, false, std::input_iterator_tag>::__copy_m<std::istream_iterator<int, char, std::char_traits<char>, long>, std::back_insert_iterator<std::vector<int, std::allocator<int> > > > (__first=..., __last=..., __result=...) at /usr/include/c++/6/bits/stl_algobase.h:293
#12 0x0000555555555965 in std::__copy_move_a<false, std::istream_iterator<int, char, std::char_traits<char>, long>, std::back_insert_iterator<std::vector<int, std::allocator<int> > > > (__first=..., __last=..., __result=...) at /usr/include/c++/6/bits/stl_algobase.h:386
#13 0x00005555555557e2 in std::__copy_move_a2<false, std::istream_iterator<int, char, std::char_traits<char>, long>, std::back_insert_iterator<std::vector<int, std::allocator<int> > > > (__first=..., __last=..., __result=...) at /usr/include/c++/6/bits/stl_algobase.h:424
#14 0x00005555555554c9 in std::copy<std::istream_iterator<int, char, std::char_traits<char>, long>, std::back_insert_iterator<std::vector<int, std::allocator<int> > > > (__first=..., __last=..., __result=...) at /usr/include/c++/6/bits/stl_algobase.h:456
#15 0x00005555555550ed in test (is=..., exceptions=true) at sample.cpp:12
#16 0x000055555555521c in main () at sample.cpp:25

展开循环,可以发现问题是最后一次调用increment,即在输入流为空时调用std::istream_iterator::operator++

仔细观察堆栈跟踪,最后的增量是在流为空时尝试 std::istream::operator>>。根据 cppreference 的说法,这将导致 failbit 被设置,因为该操作无法从流中提取整数。

关于c++ - iostream 上的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46056624/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com