Поддерживает ли BOOST_NO_EXCEPTIONS совместимость с -fno-исключениями?
Я хочу использовать Boost.Filesystem вместе с -fno-exceptions
. Согласно документации Boost.Filesystem, она заявляет, что поддерживает макрос BOOST_NO_EXCEPTIONS
.
Однако следующий фрагмент:
#define BOOST_NO_EXCEPTIONS
#include <boost/filesystem.hpp>
int main() {}
скомпилирован с помощью:
g++ -fno-exceptions boost_test.cpp
дает ошибку:
/.../boost/filesystem/operations.hpp: В конструкторе 'boost:: filesystem:: filesystem_error:: filesystem_error (const string &, повышение:: Система:: error_code) ': /.../boost/filesystem/operations.hpp:84:16: ошибка: исключение обработки отключено, используйте -fexceptions для включения catch (...) {m_imp_ptr.reset(); }
Я компилирую с помощью gcc 5 и повышаю версию 1.57 на Mac OSX (также тестировался на аналогичных настройках ubuntu).
Мне интересно, верно ли мое понимание BOOST_NO_EXCEPTIONS
в том, что оно должно охватывать использование -fno-exceptions
или просто ли оно для части boost::throw_exception
?
Ответы
Ответ 1
Ну, "нет" - это очевидный ответ здесь, g++ не может иметь дело с классом filesystem_error. Там humdinger в boost/filesystem/config.hpp:
// throw an exception ----------------------------------------------------------------//
//
// Exceptions were originally thrown via boost::throw_exception().
// As throw_exception() became more complex, it caused user error reporting
// to be harder to interpret, since the exception reported became much more complex.
// The immediate fix was to throw directly, wrapped in a macro to make any later change
// easier.
#define BOOST_FILESYSTEM_THROW(EX) throw EX
Этот макрос широко используется в libs/filesystem/src/operations.cpp для исключения исключений. Это шоу-стоппер.
Fwiw, ваша примерная программа, как представляется, компилируется должным образом в clang и MSVС++, они только жалуются на их исходные тексты о необходимости испускать код обработки исключений, g++ делает это в своем интерфейсе. Никакой жалобы от clang/msvС++ для этого образца кода, поскольку этот код обработки исключений уже был выпущен ранее, назад, когда были созданы библиотеки boost.
Что демонстрирует еще одну серьезную проблему с вашим подходом, вы, вероятно, изначально построили boost без -fno-исключений. Нехорошо.
Ответ 2
Вот что Boost.Filesystem в документации говорится:
Все исключения, создаваемые библиотекой файловой системы, реализуются путем вызова boost:: throw_exception(). Таким образом, точное поведение может отличаться в зависимости от BOOST_NO_EXCEPTIONS в момент компиляции файлов исходной файловой системы.
В моем понимании, на самом деле он не говорит, что поддерживает BOOST_NO_EXCEPTIONS
И когда я сделал egrep -r BOOST_NO_EXCEPTIONS
в каталоге файловой системы, я ничего не нашел
И после того, как я прочитал исходный код, он поддерживает мои догадки. В коде есть много мест, использующих try { ... } catch(...)
. Вы также можете указать сообщение об ошибке. Вот пример:
filesystem_error(
const std::string & what_arg, const path& path1_arg,
const path& path2_arg, system::error_code ec)
: system::system_error(ec, what_arg)
{
try
{
m_imp_ptr.reset(new m_imp);
m_imp_ptr->m_path1 = path1_arg;
m_imp_ptr->m_path2 = path2_arg;
}
catch (...) { m_imp_ptr.reset(); }
}
И если вы читаете this, семантика BOOST_NO_EXCEPTIONS
на самом деле не отключает исключения, но:
пересылка всех исключений в пользовательскую нетермическую версию повышение:: throw_exception.