Поддерживает ли 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.