Strukturované zpracování výjimek

Strukturované zpracování výjimek ( SEH  - Structured Exception Handling ) je mechanismus pro zpracování softwarových a hardwarových výjimek v operačním systému Microsoft Windows , který umožňuje programátorům ovládat zpracování výjimek a je také nástrojem pro ladění [1] .

Výjimky a zpracování výjimek

Výjimkou je událost během provádění programu, která způsobí, že se bude chovat abnormálně nebo nesprávně. Existují dva typy výjimek: hardware, který je generován procesorem , a software, generovaný operačním systémem a aplikačními programy . Strukturovaný mechanismus zpracování výjimek vám umožňuje zpracovávat softwarové i hardwarové výjimky stejným způsobem.

Implementace

Klíčová slova

Tento mechanismus je podporován pouze společností Microsoft na úrovni kompilátoru prostřednictvím implementace nestandardních konstrukcí syntaxe __trya __except. __finallyKlíčové slovo se __trypoužívá ke zvýraznění části kódu, ve které bude vyvolání výjimky zpracováno jedním nebo více bloky __except. Kód v bloku __finallybude vždy proveden bez ohledu na ostatní bloky __trya __except[2] .

Příklad použití v C a C++

__zkuste { // chráněný kód, // který je umístěn v rámci SEH } __except ( filtr výjimek ) { // obsluha výjimky } __konečně { // kód, který se má přesto spustit }

Filtry výjimek mohou být běžné funkce, které vracejí tři konstantní výrazy: [3]

  • EXCEPTION_EXECUTE_HANDLER - označuje schopnost tohoto handleru zpracovat výjimku. Po obdržení takové hodnoty operační systém zastaví vyhledávání příslušných obslužných rutin výjimek a po rozbalení zásobníku předá řízení prvnímu, který vrátil EXCEPTION_EXECUTE_HANDLER

  • EXCEPTION_CONTINUE_EXECUTION - označuje opravu chyby. Systém opět předá řízení instrukci, která výjimku vyvolala, protože se očekává, že tentokrát výjimku nevyvolá. [čtyři]
  • EXCEPTION_CONTINUE_SEARCH - označuje, že vhodný manipulátor lze nalézt výše v zásobníku. Vrácení této hodnoty zároveň může znamenat, že chyba nebyla zpracována. [3]

Použité struktury a mechanismy

Každé vlákno v libovolném procesu používá registr (16bitový selektor ) fsk uložení ukazatele na datovou strukturu informačního bloku vlákna obsahující informace o tomto vláknu. Tato struktura ukládá ukazatel na poslední registrovanou strukturu _EXCEPTION_REGISTRATION_RECORD v propojeném seznamu , který obsahuje ukazatel na obslužnou rutinu výjimky a ukazatel na předchozí položku _EXCEPTION_REGISTRATION_RECORD . [5] Když je vlákno vytvořeno, operační systém přidá výchozí obslužnou rutinu výjimek volanou souborem . kernel32!UnhandledExceptionFilter

Prototyp funkce obsluhy zpětného volání je následující:

EXCEPTION_DISPOSITION __cdecl _except_handler ( struct _EXCEPTION_RECORD * ExceptionRecord , void * EstablisherFrame , struct_CONTEXT * ContextRecord , _ void * DispatcherContext );

Pokaždé, když programátor použije konstrukci , je do zásobníku vlákna přidána__try nová instance struktury _EXCEPTION_REGISTRATION_RECORD, která ukazuje na funkci _except_handler3 knihovny msvcrt.dll . Blokový kód je volán z _except_handler3. Na konec bloku kompilátor přidá kód, který odstraní aktuální položku _EXCEPTION_REGISTRATION_RECORD a obnoví hodnotu ukazatele na předchozí položku. __except__finally__tryfs:0

Když dojde k výjimce, systém postupně projde celým řetězcem obslužných rutin přerušení. Každý obslužný program vrací hodnotu označující, zda může tuto výjimku zpracovat nebo ne. Ukazatel na konec seznamu dostupných obslužných rutin výjimek je hodnota FFFFFFFFumístěná v zásobníku za poslední obslužnou rutinou. Pokud systém nalezne požadovaný handler, pak je řízení přeneseno na něj. Zároveň po nalezení příslušného handlera pro vzniklou výjimku mu operační systém okamžitě nepřenese řízení, ale ještě jednou sekvenčně zavolá všechny handlery podél řetězce s příznakem EH_UNWINDINGk úklidu (volá destruktor ) . [4] Pokud žádný z filtrů obslužné rutiny výjimek nastavených programátorem nevrátil EXCEPTION_EXECUTE_HANDLER nebo EXCEPTION_CONTINUE_EXECUTION, provede se UnhandledExceptionFilter výchozí filtr obslužné rutiny výjimek, který je registrován, když se vlákno připravuje ke spuštění.

Volání obsluhy

Když dojde k výjimce, operační systém přímo nezavolá filtr výjimek (který je zodpovědný za to, zda konkrétní handler zpracuje výjimku, která nastala, nebo ne), ale předá svou adresu funkci _except_handler3, odkud je funkce filtru volána. . Využívá následující datovou strukturu: [6]

struktura _EXCEPTION_REGISTRATION { struct _EXCEPTION_REGISTRATION * předchozí ; void ( * handler ) ( PEXCEPTION_RECORD , PEXCEPTION_REGISTRATION , PCONTEXT , PEXCEPTION_RECORD ); struct scopetable_entry * scopetable ; int trylevel ; int_ebp ; _ PEXCEPTION_POINTERS xpointers ; };

Pole *scopetableukazuje na adresu pole struktur scopetable_entrya pole trylevel integer ukazuje na index v tomto poli. Pole _ebpobsahuje hodnotu ukazatele rámce zásobníku, který existoval před vytvořením struktury EXCEPTION_REGISTRATION. [7] Funkce _except_handler3zavolá požadovaný filtr a před voláním handleru rozbalí (vyčistí) zásobník funkcí ntdll.dll!RtlUnwind.

Pokud žádný z obslužných programů nainstalovaných programátorem nesouhlasil se zpracováním výjimky, je zavolána funkce UnhandledExceptionFilter, která zkontroluje, zda proces běží pod debuggerem , a informuje jej, zda je k dispozici. [7] Funkce poté zavolá výchozí filtr handleru (který je funkcí nastaven SetUnhandledExceptionFiltera který vždy vrátí EXCEPTION_EXECUTE_HANDLER). [7] Poté se v závislosti na nastavení operačního systému zavolá buď debugger nebo funkce NtRaiseHardError, která zobrazí chybové hlášení. [7]

Poznámky

  1. Structured Exception Handling (Windows) . Získáno 5. května 2010. Archivováno z originálu 25. září 2010.
  2. O strukturovaném zpracování výjimek (Windows) . Získáno 5. května 2010. Archivováno z originálu 28. února 2011.
  3. 1 2 Úvod do zpracování strukturovaných výjimek SEH (mrtvý odkaz) . Datum přístupu: 26. prosince 2012. Archivováno z originálu 27. března 2014. 
  4. 1 2 WASM.IN Win32 SEH Inside (část 1) . Staženo 5. dubna 2018. Archivováno z originálu 5. dubna 2018.
  5. Provoz SEH v prostředí Win32 . Získáno 1. 5. 2010. Archivováno z originálu 24. 9. 2015.
  6. WASM.IN Win32 SEH zevnitř (část 2) . Staženo 5. dubna 2018. Archivováno z originálu 5. dubna 2018.
  7. 1 2 3 4 WASM.IN Win32 SEH zevnitř (část 3) . Staženo 5. dubna 2018. Archivováno z originálu 5. dubna 2018.