Что происходит, когда код, который генерирует исключения, связан с библиотекой, скомпилированной с -fno-exceptions?
В частности, я хотел бы знать, что GCC предлагает, если таковые имеются, о том, как код, который генерирует исключения, ведет себя при соединении с кодом, скомпилированным с помощью -fno-exceptions
.
В руководстве GNU libstdc++
говорится следующее здесь.
Прежде чем подробно описать поддержку библиотеки для -fno-exceptions
, сначала обратите внимание на вещи, потерянные при использовании этого флага: они будут разбивать исключения, пытаясь передать код, скомпилированный с помощью -fno-exceptions
, имеет ли этот код какой-либо try
или catch
. Если у вас есть код, который бросает, вы не должны использовать -fno-exceptions
. Если у вас есть код, который использует try
или catch
, вы не должны использовать -fno-exceptions
.
Это звучит как выражение в строках: "Ты не должен..." I.e. undefined.
С другой стороны, мое впечатление от этого SO-вопроса заключается в том, что все кошерно, пока код, скомпилированный с -fno-exceptions
, не throw
, try
или catch
(очевидно, ошибка времени компиляции), а исключения не распространяются через функции из этой библиотеки. И это имеет смысл: почему библиотека, скомпилированная с помощью -fno-exceptions
, заботится о том, чтобы исключения были выброшены до тех пор, пока они не взаимодействуют со своими функциями?
Я немного потрудился и обнаружил, что если я скомпилирую простую программу с использованием GCC 7.1.1, в которой один исходный файл скомпилирован с помощью -fno-exceptions
, а другой выбрасывает исключение, все компилирует, связывает и работает отлично, Но это не означает, что это поведение гарантировано; он все равно может быть undefined.
Моя мотивация во всем этом заключается в том, что у меня есть ситуация, когда я связываю свой собственный код приложения с библиотекой, построенной с помощью -fno-exceptions
, и, в зависимости от того, какие вызовы функций сделаны в упомянутой библиотеке, выбрасывает исключение в мой собственный код вызывает немедленное segfault, даже если это исключение не распространяется через библиотечные функции. Мне кажется, что это ошибка в библиотеке, но я подумал, что, возможно, это было разрешено, когда во время компиляции был передан -fno-exceptions
.
GCC фактическая ссылка на флагов генерации кода упоминает -fexceptions
относительно кратко и не отвечает на мой вопрос. Кто-нибудь знает другую ссылку/имеет соответствующий опыт?
Обновление: Я перестроил библиотеку из источника, на этот раз с включенной поддержкой исключения. Segfault сохраняется! Время для отчета об ошибке.
Ответы
Ответ 1
Как указывает связанный вопрос, GCC должен разрешать -fno-exceptions
и -fexceptions
сосуществовать, чтобы связать C и С++.
На более теоретическом уровне проблема исключения тесно связана с графиком вызовов программы. Это ориентированный граф (caller/callle), но он может быть циклическим, и между узлами может быть множество ребер. Теперь каждая функция / node может быть скомпилирована с исключениями или без них. Мы можем определить безопасную программу как программу, в которой нет "с исключениями" node доступно из "без исключений" node.
Это может быть излишне строгим - может показаться разумным, что бит С++ в блоке try...catch(...) { }
должен быть вызван из кода C. Но я не знаю о гарантии GCC для этого. И подумайте, что это значит - граф вызовов связан с стеком вызовов. Стек вызовов обычно формирует путь от main()
к текущей исполняемой функции. Если весь путь является исключением, то исключения являются безопасными. Но если есть одна функция, которая не знает об исключениях, она могла бы поставить стек в состояние, в котором исключения не могут быть безопасно обработаны, даже если раскрутка стека не будет так далеко.