Как C++ обработката на изключения се превежда в машинен код

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

Нормалният стек използва ли се за следене на trys, или отделен стек за нишка се съхранява само за тази цел? Внедряването между MSVC и g++ голямо или малко ли е? Моля, покажете ми някакъв псевдо asm (IA-32 също е ок), така че никога да не се налага да го проверявам сам! :)

Редактиране: Сега разбирам основите на внедряването на MSVC при работа с IA-32. Някой знае ли за g++ на IA-32 или друг CPU по този въпрос?

Редактиране 2 (11 години по-късно): Ето някои данни за ефективността. Те също направиха изходния код свободно достъпен.


person Jonas Byström    schedule 25.08.2009    source източник


Отговори (3)


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

Това е лоша реализация, тъй като програмата плаща цена за време на изпълнение за всяка клауза за опит (натискане, след това изскачане), дори когато не възникне изключение.

Добрите реализации просто записват таблица с диапазони, където се срещат клаузи за опит. Това означава, че няма нулеви разходи за влизане/излизане от клауза за опит. (Моят PARLANSE език за паралелно програмиране използва тази техника). Изключение търси компютъра на точката на изключение в таблицата и предава контрола на EH, избран от таблицата. EH кодът нулира стека, както е подходящо. Бързо и красиво. Мисля, че Windows 64 bit EH е от този тип, но не съм гледал внимателно.

[РЕДАКТИРАНЕ април 2020 г.: Току-що измери цената на изключенията на PARLANSE наскоро. 0nS (по дизайн), ако няма изключение; 25ns на 3Ghz i7 от хвърляне до улавяне до потвърждаване (краен празен улов). OP добави връзка, измерваща C++ обработката на изключения при приблизително 1000ns за най-простия вид и буквално нестандартна схема за обработка, която се записва на 57ns за изключение или без изключение; Тактовите честоти на процесора за версиите на C++ са малко по-бавни, така че тези числа са само за грубо сравнение.]

person Ira Baxter    schedule 25.08.2009
comment
Връзката е мъртва. - person Ekrem Dinçel; 30.11.2020
comment
@Kowalski: благодаря, че посочи това. Връзката е фиксирана. - person Ira Baxter; 30.11.2020
comment
@IraBaxter Връзката PARLANSE не работи за мен (времето за изчакване на връзката изтече). Потърсих го в Google и там се появи същия проблем. - person Sourav Kannantha B; 15.02.2021
comment
@Sourav: Ние сме в Остин Тексас, току-що получихме 6 инча сняг (рекорд от век) и захранването е спряно в целия град -› сървърите ни не работят. Задръжте дъха си за 1/2 ден и опитайте отново. - person Ira Baxter; 15.02.2021
comment
@IraBaxter Да предположим, че хипотетичен език предоставя кратък и по-чист синтаксис за писане на базов стил за обработка на код за грешка, тогава кой бихте предпочели? код на грешка или изключения? - person Sourav Kannantha B; 15.02.2021
comment
Изключения, особено тези, които имат нулева цена, когато не се случват. а) не трябва да напишете тест за код за грешка, който проверява за всяка грешка във всяка точка, където може да възникне такава, и б) намалява цената на проверката за грешка. PARLANSE притежава този хубав имот през последните 20 години. - person Ira Baxter; 16.02.2021

Комитетът по стандартите на C++ публикува технически доклад за „производителността на C++“, за да развенчае много митове за това как функциите на C++ уж ви забавят. Това също включва подробности за това как може да се приложи обработката на изключения. Черновата на този технически доклад е достъпна безплатно. Проверете раздел 5.4.1. „Проблеми и техники за внедряване на обработка на изключения“.

person sellibitze    schedule 03.10.2009

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

x86-64 System V използва секцията .eh_frame за метаданни за разгъване на стека, така че библиотечните функции за подпомагане на изключения знаят как да обикалят стека и да възстановяват регистрите. Това правят директивите .cfi.

person Peter Cordes    schedule 03.08.2018
comment
Не можах да реша дали да публикувам този едва отговор като коментар или не. Отидох с отговор, въпреки че не отделих време да навляза в подробности или да покажа и коментирам кода. - person Peter Cordes; 03.08.2018