Реализации могут отличаться, но есть несколько основных идей, которые вытекают из требований.
Сам объект исключения - это объект, созданный в одной функции, уничтоженный в ее вызывающей стороне. Следовательно, обычно невозможно создать объект в стеке. С другой стороны, многие объекты исключений не очень большие. Следовательно, можно создать, например, 32-байтовый буфер и переполнить его в кучу, если действительно нужен более крупный объект исключения.
Что касается фактической передачи контроля, существует две стратегии. Один из них - записать достаточно информации в сам стек, чтобы раскрутить стек. По сути, это список деструкторов для запуска и обработчиков исключений, которые могут перехватить исключение. Когда происходит исключение, запустите стек, выполняя эти деструкторы, пока не найдете подходящий улов.
Вторая стратегия перемещает эту информацию в таблицы вне стека. Теперь, когда возникает исключение, стек вызовов используется, чтобы узнать, в какие области входят, но не выходят. Затем они просматриваются в статических таблицах, чтобы определить, где будет обрабатываться выброшенное исключение и какие деструкторы будут выполняться между ними. Это означает, что в стеке меньше накладных расходов на исключение; Обратные адреса все равно нужны. Таблицы представляют собой дополнительные данные, но компилятор может поместить их в загружаемый по запросу сегмент программы.