C ++ try / throw / catch => машинный код - PullRequest
39 голосов
/ 26 августа 2009

Мысленно я всегда задавался вопросом, как try / throw / catch выглядит за кулисами, когда компиляция C ++ переводит его на ассемблер. Но так как я никогда не использую его, я никогда не удосужился проверить его (некоторые люди сказали бы, что он ленивый).

Используется ли обычный стек для отслеживания try с, или отдельный стек для каждого потока хранится только для этой цели? Является ли реализация между MSVC и g ++ большой или маленькой? Пожалуйста, покажите мне немного псевдо-ассма (IA-32 тоже хорошо), так что мне никогда не придется проверять это самому! :)

Редактировать: Теперь я получил основы реализации MSVC по обработке IA-32. Кто-нибудь знает g ++ на IA-32 или любой другой процессор в этом отношении?

Ответы [ 6 ]

20 голосов
/ 26 августа 2009

Плохие реализации обработчиков исключений выдвигают какой-то блок обработчиков исключений для каждого предложения try в стеке времени выполнения при вводе предложения try и извлекают его при выходе из предложения try. Местоположение, содержащее адрес самого последнего отправленного блока обработчика исключений, также сохраняется. Как правило, эти обработчики исключений связаны между собой, поэтому их можно найти по ссылкам с самых последних версий. Когда возникает исключение, обнаруживается указатель на последний обработанный блок обработчика EH, и проверяется обработка случаев EH этого предложения try. Попадание в дело EH приводит к тому, что очистка стека происходит обратно в точку выдвинутого EH, и управление переходит в дело EH. Отсутствие попаданий в EH приводит к обнаружению следующего EH, и процесс повторяется. 32-битная схема SEH для Windows является версией этого.

Это плохая реализация, потому что программа платит цену выполнения за каждое предложение try (push затем pop), даже когда исключение не происходит.

Хорошие реализации просто записывают таблицу диапазонов, в которых встречаются предложения try. Это означает, что на вход / выход из предложения try накладных расходов нет. (Мой PARLANSE язык программирования Parallell использует эту технику). Исключение ищет ПК точки исключения в таблице и передает управление EH, выбранному таблицей. Код EH сбрасывает стек соответствующим образом. Быстро и красиво. Я думаю, что Windows 64-битный EH относится к этому типу, но я не посмотрел внимательно.

15 голосов
/ 26 августа 2009

Это очень ценная статья на эту тему: Как компилятор C ++ реализует обработку исключений

9 голосов
/ 26 августа 2009

В журнале Microsoft Journal "Под капотом" в 1997 году был подробно рассмотрен этот вопрос:

Ускоренный курс по глубине структурной обработки исключений Win32 ™

4 голосов
/ 03 октября 2009

Комитет по стандартизации C ++ опубликовал технический отчет о «производительности C ++», чтобы развенчать многие мифы о том, как возможности C ++, возможно, замедляют вас. Это также включает подробности о том, как можно реализовать обработку исключений. Черновик данного технического отчета доступен бесплатно. Проверьте раздел 5.4.1. «Проблемы и методы реализации обработки исключений».

0 голосов
/ 03 августа 2018

Asm из проводника компилятора Godbolt , для соглашения о вызовах System V x86-64 с C ++ ABI g ++ 8.2, для функции, которая перехватывает, и тот, который бросает.

x86-64 System V использует секцию .eh_frame для метаданных с размоткой стека, поэтому функции библиотеки-помощника исключений знают, как обходить стек и восстанавливать регистры. Это то, что делают директивы .cfi.

0 голосов
/ 26 августа 2009

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

...