Исключения в boost :: iostreams :: multichar_input_filter исчезают при компиляции кода с помощью Visual Studio - PullRequest
0 голосов
/ 18 января 2019

Я работаю над потоковым фильтром, который может декодировать пользовательский формат файла. Моя цель - использовать boost::iostreams::filtering_istream для чтения файла и обработки его с моим подклассом boost::iostreams::multichar_input_filter, чтобы я мог загружать значения с помощью оператора <<.

Я также хочу, чтобы процесс был остановлен, когда мой фильтр не может декодировать поток и выдает исключение, что происходит, когда я компилирую код с использованием gcc 5.4 в подсистеме Windows для Linux, но исключение проглатывается до того, как оно достигнет моего кода, если Я компилирую с VS2017.

Я использую Boost 1.68.0 как для Windows, так и для WSL; Я собрал и установил его, используя b2 на обеих платформах, без каких-либо пользовательских аргументов или настроек. Я также пробовал 1.58.0 на WSL, который приходит из менеджера пакетов.

В проекте используется CMake, и я ничего не настраивал ни в CMakeSettings.json, ни в launch.vs.json.

Я создал этот упрощенный код, который показывает, как я использую цепочку фильтров, класс исключений и как я пытаюсь отловить ошибку обработки:

#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;
}

Я ожидаю, что этот код запишет сообщение «Ожидаемое исключение» в выходной файл и завершится с кодом возврата 1 на всех платформах. Однако, когда я компилирую его с помощью Visual Studio, он выводит некоторый мусор и возвращает код 0.

1 Ответ

0 голосов
/ 18 января 2019

Я думаю, что это ошибка в старом 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;
}

также см. документация об исключениях iostream

...