Подтвердить что ты не робот

Что происходит, когда код, который генерирует исключения, связан с библиотекой, скомпилированной с -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 сохраняется! Время для отчета об ошибке.

4b9b3361

Ответ 1

Как указывает связанный вопрос, GCC должен разрешать -fno-exceptions и -fexceptions сосуществовать, чтобы связать C и С++.

На более теоретическом уровне проблема исключения тесно связана с графиком вызовов программы. Это ориентированный граф (caller/callle), но он может быть циклическим, и между узлами может быть множество ребер. Теперь каждая функция / node может быть скомпилирована с исключениями или без них. Мы можем определить безопасную программу как программу, в которой нет "с исключениями" node доступно из "без исключений" node.

Это может быть излишне строгим - может показаться разумным, что бит С++ в блоке try...catch(...) { } должен быть вызван из кода C. Но я не знаю о гарантии GCC для этого. И подумайте, что это значит - граф вызовов связан с стеком вызовов. Стек вызовов обычно формирует путь от main() к текущей исполняемой функции. Если весь путь является исключением, то исключения являются безопасными. Но если есть одна функция, которая не знает об исключениях, она могла бы поставить стек в состояние, в котором исключения не могут быть безопасно обработаны, даже если раскрутка стека не будет так далеко.