Struktureret undtagelseshåndtering

Struktureret undtagelseshåndtering ( SEH  - Structured Exception Handling ) er en mekanisme til håndtering af software- og hardwareundtagelser i Microsoft Windows -operativsystemet, der tillader programmører at kontrollere undtagelseshåndtering, og er også et fejlfindingsværktøj [ 1 ] .

Undtagelser og undtagelseshåndtering

En undtagelse er en hændelse under programafvikling, der får det til at opføre sig unormalt eller forkert. Der er to typer undtagelser: hardware, som genereres af processoren , og software, genereret af operativsystemet og applikationsprogrammer . Den strukturerede undtagelseshåndteringsmekanisme giver dig mulighed for at håndtere både software- og hardwareundtagelser på samme måde.

Implementering

Nøgleord

Mekanismen understøttes kun af Microsoftcompilerniveau gennem implementeringen af ​​de ikke-standardiserede syntakskonstruktioner __tryog __except. __finallyNøgleordet __trybruges til at fremhæve en kodesektion, hvor udsendelsen af ​​en undtagelse vil blive håndteret af en eller flere blokke __except. Koden i blokken __finallyvil altid blive udført uanset andre blokke __tryog __except[2] .

Eksempel på brug i C og C++

__prøve { // beskyttet kode, // som er placeret i en SEH-ramme } __except ( undtagelsesfilter ) { _ // undtagelseshandler } __endelig { // kode til at køre alligevel }

Undtagelsesfiltre kan være almindelige funktioner, der returnerer tre konstante udtryk: [3]

  • EXCEPTION_EXECUTE_HANDLER - angiver denne handlers evne til at håndtere undtagelsen. Ved modtagelse af en sådan værdi, stopper operativsystemet med at søge efter relevante undtagelsesbehandlere, og efter at have afviklet stakken, overfører det kontrollen til den første, der returnerede EXCEPTION_EXECUTE_HANDLER

  • EXCEPTION_CONTINUE_EXECUTION - indikerer en fejlrettelse. Systemet vil igen overføre kontrollen til den instruktion, der afstedkom undtagelsen, fordi det forventes, at det denne gang ikke vil kaste en undtagelse. [fire]
  • EXCEPTION_CONTINUE_SEARCH - angiver, at en passende handler kan findes højere oppe i stakken. Samtidig kan returnering af denne værdi indikere, at fejlen ikke er blevet håndteret. [3]

Anvendte strukturer og mekanismer

Hver tråd i enhver proces bruger et register (16-bit vælger ) fstil at gemme en pointer til en trådinformationsblok- datastruktur, der indeholder information om den tråd. Denne struktur gemmer en pointer til den sidst registrerede _EXCEPTION_REGISTRATION_RECORD struktur i den sammenkædede liste , som inkluderer en pointer til undtagelsesbehandleren og en pointer til den forrige _EXCEPTION_REGISTRATION_RECORD- indgang . [5] Når en tråd oprettes, tilføjer operativsystemet en standard undtagelseshåndtering kaldet af . kernel32!UnhandledExceptionFilter

Prototypen af ​​tilbagekaldshåndteringsfunktionen er som følger:

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

Hver gang programmøren bruger konstruktionen , tilføjes__try en ny instans af strukturen _EXCEPTION_REGISTRATION_RECORD, der peger på funktionen _except_handler3 i biblioteket msvcrt.dll , til trådens stak . Blokkoden kaldes fra _except_handler3. I slutningen af ​​blokken tilføjer compileren kode, der fjerner den aktuelle _EXCEPTION_REGISTRATION_RECORD-indgang og gendanner værdien af ​​markøren til den forrige post. __except__finally__tryfs:0

Når der opstår en undtagelse, itererer systemet gennem hele kæden af ​​interrupt-handlere i rækkefølge. Hver handler returnerer en værdi, der angiver, om den kan håndtere denne undtagelse eller ej. Markøren til slutningen af ​​listen over tilgængelige undtagelsesbehandlere er værdien FFFFFFFFplaceret på stakken efter den sidste behandler. Hvis systemet finder den ønskede handler, overføres kontrollen til den. På samme tid, efter at have fundet den relevante handler for den opståede undtagelse, overfører operativsystemet ikke øjeblikkeligt kontrol til det, men kalder igen sekventielt alle handlere langs kæden med flaget EH_UNWINDINGfor at rydde op (kald destruktoren ) . [4] Hvis ingen af ​​de undtagelsesbehandlerfiltre, der er indstillet af programmøren, returnerede EXCEPTION_EXECUTE_HANDLER eller EXCEPTION_CONTINUE_EXECUTION, UnhandledExceptionFilter udføres standard undtagelseshåndteringsfilteret, som registreres, når tråden forbereder at køre.

Behandleropkald

Når en undtagelse opstår, kalder operativsystemet ikke direkte undtagelsesfilteret (som er ansvarligt for, om en bestemt behandler vil håndtere den opståede undtagelse eller ej), men sender sin adresse til funktionen _except_handler3, hvorfra filterfunktionen kaldes . Den bruger følgende datastruktur: [6]

struktur _EXCEPTION_REGISTRATION { struct _EXCEPTION_REGISTRATION * forrige ; void ( * handler )( PEXCEPTION_RECORD , PEXCEPTION_REGISTRATION , PCONTEXT , PEXCEPTION_RECORD ); struct scopetable_entry * scopetable ; int trylevel ; int_ebp ; _ PEXCEPTION_POINTERS xpointere ; };

Feltet *scopetablepeger på adressen på et array af strukturer scopetable_entry, og trylevel-heltalsfeltet peger på et indeks i dette array. Feltet _ebpindeholder værdien af ​​stak frame pointer, der eksisterede før oprettelsen af ​​EXCEPTION_REGISTRATION strukturen. [7] Funktionen _except_handler3kalder det påkrævede filter og, før du kalder handleren, afvikler (renser) stakken med funktionen ntdll.dll!RtlUnwind.

Hvis ingen af ​​de behandlere installeret af programmøren accepterede at håndtere undtagelsen, kaldes en funktion, UnhandledExceptionFilterder kontrollerer, om processen kører under debuggeren , og informerer den, om den er tilgængelig. [7] Funktionen kalder derefter standardbehandlerfilteret (som er sat af funktionen, SetUnhandledExceptionFilterog som altid returnerer EXCEPTION_EXECUTE_HANDLER). [7] Derefter kaldes enten fejlfinderen eller NtRaiseHardError-funktionen, afhængigt af operativsystemets indstillinger, som viser en fejlmeddelelse. [7]

Noter

  1. Håndtering af struktureret undtagelser (Windows) . Hentet 5. maj 2010. Arkiveret fra originalen 25. september 2010.
  2. Om struktureret undtagelseshåndtering (Windows) . Hentet 5. maj 2010. Arkiveret fra originalen 28. februar 2011.
  3. 1 2 Introduktion til SEH Structured Exception Handling (dødt link) . Dato for adgang: 26. december 2012. Arkiveret fra originalen 27. marts 2014. 
  4. 1 2 WASM.IN Win32 SEH Inside (Del 1) . Hentet 5. april 2018. Arkiveret fra originalen 5. april 2018.
  5. Betjening af SEH i et Win32-miljø . Hentet 1. maj 2010. Arkiveret fra originalen 24. september 2015.
  6. WASM.IN Win32 SEH indefra (del 2) . Hentet 5. april 2018. Arkiveret fra originalen 5. april 2018.
  7. 1 2 3 4 WASM.IN Win32 SEH indefra (del 3) . Hentet 5. april 2018. Arkiveret fra originalen 5. april 2018.