Exceptions on iostreams
Exceptions on iostreams
我最近了解到,可以选择加入iostreams的例外。为了不必手动检查文件是否打开,我尝试过并遇到此行为:
#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 3n4 5 6n7 8 9n");
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
展开循环,您可以发现这是引起问题的最后一个呼叫,即输入流是空的 std::istream_iterator::operator++
。
仔细观察堆栈跟踪,最终增量正在尝试std :: istream ::操作员>>当流为空时。根据CPPReference,这将导致设置故障,因为该操作未能从流中提取整数。
jonesinator给您提供了例外的原因,我想强调的是,从异常中,是否独立存在错误。实际上,您的功能不是等效的,您不会在无外部分支机构操作后检查流。实际上,错误会默默发生。如果您以同等方式编写两个函数,则将获得同等结果:
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>
void test_exception(std::istream& is) {
try {
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::cout << "Caught error: " << f.what() << 'n';
}
}
void test_error_code(std::istream& is) {
std::vector<int> input;
std::copy(std::istream_iterator<int>{is}, {}, std::back_inserter(input));
if (!is.good()) {
std::cout << "Caught error!" << std::endl;
return;
}
for (auto x : input) {
std::cout << x << 'n';
}
}
int main() {
// Emulates file
std::stringstream ss_error_code("1 2 3n4 5 6n7 8 9n");
test_error_code(ss_error_code);
std::stringstream ss_exception("1 2 3n4 5 6n7 8 9n");
test_exception(ss_exception);
}
输出:
捕获错误!
抓取错误:basic_ios :: clear
imho,这是一个很好的例子,为什么例外在绝大多数方案中都优于结果代码,并且应将其用作默认情况。
相关文章:
- 瓦尔格林德:数学函数"Conditional jump or move depends on uninitialised value(s)"
- 隐式声明的 boost::iostreams::mapped_file_source 已被弃用
- 循环挂起迭代的 std::擦除 on std::list
- SIGSEGV on Boost UDP 套接字关闭 - tcache_get at malloc.c.
- CPP 中的瓦尔格林德和记忆泄漏:"Conditional jump or move depends on uninitialised values"
- std::bind on statd::array 的运算符 []
- 您将如何连接"on the fly"文本+整数并将其传递给函数?
- 如何修复输出日志中的"EnableInput can only be specified on a Pawn for its Controller"错误
- VS2019 - Sudo Remote Debugging on Linux with Cmake project
- C++ library with Tensorflow on Android
- SFML 交叉编译 for Windows on Linux.
- How to recover system gcc compiler on centos 6
- Cmake with Flex/Bison on windows
- 按原样保存用户输入 - Ruby on Rails
- OpenAL C++ on Linux
- Boost::process on Windows - with MinGW?
- CMake on FindOpenGL.cmake 中的错误,当使用导入的目标 OpenGL::GLU?
- Utilization of atomic_flag on C++
- anaconda cythonize C++ on windows 10
- Exceptions on iostreams