boost::iostreams::multichar_input_filter 中的异常在使用 Visual Studio 编译代码时消失
Exceptions in boost::iostreams::multichar_input_filter disappear when code is compiled with Visual Studio
我正在研究可以解码自定义文件格式的流过滤器。我的目标是使用 boost::iostreams::filtering_istream
读取文件并使用我的 boost::iostreams::multichar_input_filter
subclass 处理它,以便我可以使用 <<
运算符加载值。
我还希望当我的过滤器无法解码流并抛出异常时终止进程,当我在 Windows 子系统 Linux 上使用 gcc 5.4 编译代码时会发生这种情况,但是如果我用 VS2017 编译,异常在到达我的代码之前就被吞没了。
我在 Windows 和 WSL 上都使用 Boost 1.68.0;我已经在两个平台上使用 b2 构建并安装了它,没有任何自定义参数或配置。我也在 WSL 上试过 1.58.0,它来自包管理器。
该项目使用CMake,我在CMakeSettings.json和launch.vs.json中没有自定义任何东西。
我创建了这个简化的代码,展示了我如何使用过滤器链、异常 class 以及我如何尝试捕获处理错误:
#include <iostream>
#include <boost/iostreams/concepts.hpp> // multichar_input_filter
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/throw_exception.hpp>
using namespace std;
namespace io = boost::iostreams;
class TestFilterException : public BOOST_IOSTREAMS_FAILURE {
public:
explicit TestFilterException(const char* message) : BOOST_IOSTREAMS_FAILURE(message) {
}
};
class TestFilter : public io::multichar_input_filter {
public:
explicit TestFilter() {
}
template <typename Source> streamsize read(Source& src, char* output_buffer, streamsize requested_char_count) {
BOOST_THROW_EXCEPTION(TestFilterException("Something went wrong"));
}
template <typename Source> void close(Source&) {
}
};
int main(const int argc, const char *argv[]) {
char buffer[64] = {'x'};
io::array_source source = io::array_source(buffer);
io::filtering_istream in;
in.push(TestFilter());
in.push(source);
char c;
try {
in >> c;
cout << c;
} catch (boost::exception& e) {
cout << "Expected exception";
return 1;
}
return 0;
}
我希望此代码将 'Expected exception' 消息写入输出并在所有平台上以 return 代码 1
退出。但是,当我用 Visual Studio 编译它时,它会输出一些垃圾和 returns 代码 0
。
我认为这是旧版 gcc 中的错误。较新的 gcc 和 VS 正确捕获抛出的异常并设置坏位标志,而不是通过流方法传播异常。打印垃圾是因为 c
在读取尝试失败后未初始化。您可以通过在流中设置异常标志使流抛出错误位异常:
try
{
io::filtering_istream in;
in.exceptions(::std::ios_base::badbit | ::std::ios_base::failbit | ::std::ios_base::eofbit);
in.push(TestFilter());
in.push(source);
char c;
in >> c;
cout << c;
} catch (boost::exception& e) {
cout << "not expected boost exception";
return 1;
}
catch(::std::exception const & e)
{
cout << "Expected std exception";
return 2;
}
我正在研究可以解码自定义文件格式的流过滤器。我的目标是使用 boost::iostreams::filtering_istream
读取文件并使用我的 boost::iostreams::multichar_input_filter
subclass 处理它,以便我可以使用 <<
运算符加载值。
我还希望当我的过滤器无法解码流并抛出异常时终止进程,当我在 Windows 子系统 Linux 上使用 gcc 5.4 编译代码时会发生这种情况,但是如果我用 VS2017 编译,异常在到达我的代码之前就被吞没了。
我在 Windows 和 WSL 上都使用 Boost 1.68.0;我已经在两个平台上使用 b2 构建并安装了它,没有任何自定义参数或配置。我也在 WSL 上试过 1.58.0,它来自包管理器。
该项目使用CMake,我在CMakeSettings.json和launch.vs.json中没有自定义任何东西。
我创建了这个简化的代码,展示了我如何使用过滤器链、异常 class 以及我如何尝试捕获处理错误:
#include <iostream>
#include <boost/iostreams/concepts.hpp> // multichar_input_filter
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/throw_exception.hpp>
using namespace std;
namespace io = boost::iostreams;
class TestFilterException : public BOOST_IOSTREAMS_FAILURE {
public:
explicit TestFilterException(const char* message) : BOOST_IOSTREAMS_FAILURE(message) {
}
};
class TestFilter : public io::multichar_input_filter {
public:
explicit TestFilter() {
}
template <typename Source> streamsize read(Source& src, char* output_buffer, streamsize requested_char_count) {
BOOST_THROW_EXCEPTION(TestFilterException("Something went wrong"));
}
template <typename Source> void close(Source&) {
}
};
int main(const int argc, const char *argv[]) {
char buffer[64] = {'x'};
io::array_source source = io::array_source(buffer);
io::filtering_istream in;
in.push(TestFilter());
in.push(source);
char c;
try {
in >> c;
cout << c;
} catch (boost::exception& e) {
cout << "Expected exception";
return 1;
}
return 0;
}
我希望此代码将 'Expected exception' 消息写入输出并在所有平台上以 return 代码 1
退出。但是,当我用 Visual Studio 编译它时,它会输出一些垃圾和 returns 代码 0
。
我认为这是旧版 gcc 中的错误。较新的 gcc 和 VS 正确捕获抛出的异常并设置坏位标志,而不是通过流方法传播异常。打印垃圾是因为 c
在读取尝试失败后未初始化。您可以通过在流中设置异常标志使流抛出错误位异常:
try
{
io::filtering_istream in;
in.exceptions(::std::ios_base::badbit | ::std::ios_base::failbit | ::std::ios_base::eofbit);
in.push(TestFilter());
in.push(source);
char c;
in >> c;
cout << c;
} catch (boost::exception& e) {
cout << "not expected boost exception";
return 1;
}
catch(::std::exception const & e)
{
cout << "Expected std exception";
return 2;
}