Что представляет собой механизм разматывания стопки?

Я пытаюсь понять механизм раскручивания стека в C++. Другими словами, меня интересует, как эта функция реализована (и является ли она частью стандарта).

Таким образом, поток выполняет некоторый код, пока не возникнет исключение. Когда возникает исключение, какие потоки/обработчики прерываний используются для записи состояния и очистки стека? Что гарантирует стандарт и что зависит от реализации?

Нет, прерываний нет. Я думаю, вы путаете исключения C++ с исключениями более низкого уровня.

molbdnilo 11.11.2022 09:34

Стандарт C++ дает только общие требования, поэтому он может различаться в зависимости от операционной системы и даже выбора среды выполнения в одной и той же операционной системе. Что вызывает такие вопросы: stackoverflow.com/questions/15670169/…

Öö Tiib 11.11.2022 09:41

На некоторые части этого вопроса можно ответить, поэтому StackOverflow рекомендует задавать по одному вопросу на вопрос. Разматывание стека выполняется, например, в потоке, вызвавшем исключение.

MSalters 11.11.2022 10:40
[JS за 1 час] - 9. Асинхронный
[JS за 1 час] - 9. Асинхронный
JavaScript является однопоточным, то есть он может обрабатывать только одну задачу за раз. Для обработки длительных задач, таких как сетевые запросы,...
Топ-10 компаний-разработчиков PHP
Топ-10 компаний-разработчиков PHP
Если вы ищете надежных разработчиков PHP рядом с вами, вот список лучших компаний по разработке PHP.
Скраппинг поиска Apple App Store с помощью Python
Скраппинг поиска Apple App Store с помощью Python
📌Примечание: В этой статье я покажу вам, как скрапировать поиск Apple App Store и получить точно такой же результат, как на Apple iMac, потому что...
Редкие достижения на Github ✨
Редкие достижения на Github ✨
Редкая коллекция доступна в профиле на GitHub ✨
Подъем в javascript
Подъем в javascript
Hoisting - это поведение в JavaScript, при котором переменные и объявления функций автоматически "перемещаются" в верхнюю часть соответствующих...
Улучшение генерации файлов Angular
Улучшение генерации файлов Angular
Angular - это фреймворк. Вы можете создать практически любое приложение без использования сторонних библиотек.
1
3
99
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поток выполняет некоторый код до тех пор, пока не возникнет исключение, и он продолжает это делать. Обработка исключений по-прежнему является кодом C++.

Выражение throw создает объект C++, работающий в контексте бросающей функции. Пока работает конструктор объекта-исключения, все объекты в области действия вызывающей функции все еще живы.

Однако сразу после этого происходит раскрутка стека. Компилятор C++ организует обратный путь, который не требует возвращаемого объекта, но позволяет передавать объект исключения. Как и при обычном возврате, объекты, которые являются локальными для функции, уничтожаются, когда функция возвращается. На двоичном уровне это довольно просто: это всего лишь набор вызовов деструктора, и обычно также корректируется указатель стека.

Что стандарт также не определяет, так это механизм, используемый для определения того, из скольких областей необходимо выйти. Стандарт описывает в терминах catch, но типичный ЦП не имеет прямого эквивалента. Следовательно, это обычно является частью C++ ABI для данной платформы, поэтому компиляторы, использующие ABI, согласны. Совместимость с ABI требует, чтобы вызывающий объект перехватывал исключения от вызываемого объекта, даже если они были скомпилированы с помощью разных компиляторов. И, очевидно, деструкторы должны быть вызваны, поэтому ABI также должен организовать этот механизм. Промежуточные функции могли быть даже скомпилированы третьим компилятором — пока они имеют общий ABI, все должно работать.

Как отмечено в комментариях, C++ не имеет понятия о прерываниях. Если ОС нужно, чтобы что-то происходило с прерываниями, об этом должен позаботиться компилятор. Неважно, что именно делает код C++ в это время.

Я думаю, что в тексте есть немного неточное утверждение: это не совсем обратный путь, который позволяет передать объект исключения; это звучит так, как будто функция способна альтернативно возвращать объект исключения, хотя я не думаю, что на самом деле это происходит. Код очистки каждой функции в стеке вызывается кодом раскручивания стека, но он не получает и не возвращает объект исключения. catch оговорки получают, но опять же не возвращают.

Mike Nakis 20.11.2022 16:33

Можно привести пару примеров того, как предложения catch и finally могут быть обнаружены кодом раскручивания стека. Один из способов — всегда помещать в стек специальное дозорное значение в try и помещать его в конец предложения try-catch-finally. Затем код раскручивания стека должен только посмотреть значение прямо перед адресом возврата в стеке.

Mike Nakis 20.11.2022 16:38

Другой способ — всегда следовать за каждой инструкцией call с относительным переходом на несколько байтов дальше и сохранять контрольное значение в этих байтах. Это работает немного лучше в обычных условиях, но требует больше работы во время раскручивания стека, потому что раскручивателю стека теперь нужно просмотреть код по адресу возврата, но в целом это нормально.

Mike Nakis 20.11.2022 16:38

Другие вопросы по теме