Strukturoitu poikkeuskäsittely

Strukturoitu poikkeuskäsittely ( SEH  - Structured Exception Handling ) on Microsoft Windows -käyttöjärjestelmän ohjelmisto- ja laitteistopoikkeuksien käsittelymekanismi , jonka avulla ohjelmoijat voivat hallita poikkeusten käsittelyä, ja se on myös virheenkorjaustyökalu [1] .

Poikkeukset ja poikkeusten käsittely

Poikkeus on tapahtuma ohjelman suorittamisen aikana, joka saa sen toimimaan epänormaalisti tai virheellisesti. Poikkeuksia on kahdenlaisia: prosessorin luomat laitteistot ja käyttöjärjestelmän ja sovellusohjelmien luomat ohjelmistot . Strukturoidun poikkeusten käsittelymekanismin avulla voit käsitellä sekä ohjelmisto- että laitteistopoikkeuksia samalla tavalla.

Toteutus

Avainsanat

Microsoft tukee tätä mekanismia vain kääntäjätasolla toteuttamalla epätyypillisiä syntaksirakenteita __tryja __except. __finallyAvainsanaa __trykäytetään korostamaan koodin osa, jossa yksi tai useampi lohko käsittelee poikkeuksen heittoa __except. Lohkossa oleva koodi __finallysuoritetaan aina riippumatta muista lohkoista __tryja __except[2] .

Käyttöesimerkki C:ssä ja C++:ssa

__yritä { // suojattu koodi, // joka on sijoitettu SEH-kehykseen } __except ( poikkeussuodatin ) { _ // poikkeuskäsittelijä } __vihdoin { // koodi, joka suoritetaan joka tapauksessa }

Poikkeussuodattimet voivat olla tavallisia funktioita, jotka palauttavat kolme vakiolauseketta: [3]

  • EXCEPTION_EXECUTE_HANDLER - osoittaa tämän käsittelijän kyvyn käsitellä poikkeusta. Vastaanotettuaan tällaisen arvon käyttöjärjestelmä lopettaa asiaankuuluvien poikkeuskäsittelijöiden etsimisen ja siirtää pinon purkamisen jälkeen ohjauksen ensimmäiselle, joka palautti EXCEPTION_EXECUTE_HANDLER

  • EXCEPTION_CONTINUE_EXECUTION - ilmaisee virheenkorjauksen. Järjestelmä siirtää ohjauksen jälleen poikkeuksen tehneelle käskylle, koska on odotettavissa, että tällä kertaa se ei tee poikkeusta. [neljä]
  • EXCEPTION_CONTINUE_SEARCH - osoittaa, että sopiva käsittelijä löytyy pinon ylemmältä. Samanaikaisesti tämän arvon palauttaminen voi tarkoittaa, että virhettä ei ole käsitelty. [3]

Käytetyt rakenteet ja mekanismit

Jokainen säie missä tahansa prosessissa käyttää rekisteriä (16-bittinen valitsin ) fstallentaakseen osoittimen säietietolohkon tietorakenteeseen, joka sisältää tietoja kyseisestä säikeestä. Tämä rakenne tallentaa osoittimen viimeksi rekisteröityyn _EXCEPTION_REGISTRATION_RECORD- rakenteeseen linkitetyssä luettelossa , joka sisältää osoittimen poikkeuskäsittelijään ja osoittimen edelliseen _EXCEPTION_REGISTRATION_RECORD- merkintään . [5] Kun säiettä luodaan, käyttöjärjestelmä lisää oletusarvoisen poikkeuskäsittelijän , jota kutsuu . kernel32!UnhandledExceptionFilter

Takaisinsoittokäsittelijän toiminnon prototyyppi on seuraava:

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

Joka kerta kun ohjelmoija käyttää konstruktia , säikeen pinoon lisätään__try uusi _EXCEPTION_REGISTRATION_RECORD-rakenteen ilmentymä, joka osoittaa msvcrt.dll - kirjaston _except_handler3-funktioon . Estokoodi kutsutaan _paitsi_käsittelijästä3 . Lohkon loppuun kääntäjä lisää koodin, joka poistaa nykyisen _EXCEPTION_REGISTRATION_RECORD-merkinnän ja palauttaa osoittimen arvon edelliseen merkintään. __except__finally__tryfs:0

Poikkeuksen sattuessa järjestelmä toistuu koko keskeytyskäsittelijöiden ketjun läpi peräkkäin. Jokainen käsittelijä palauttaa arvon, joka osoittaa, pystyykö se käsittelemään tämän poikkeuksen vai ei. Osoitin käytettävissä olevien poikkeuskäsittelijöiden luettelon loppuun on arvo FFFFFFFF, joka sijaitsee pinossa viimeisen käsittelijän jälkeen. Jos järjestelmä löytää halutun käsittelijän, ohjaus siirtyy sille. Samaan aikaan, löydettyään asianmukainen käsittelijä syntyneelle poikkeukselle, käyttöjärjestelmä ei siirrä välittömästi ohjausta sille, vaan kutsuu jälleen kerran peräkkäin kaikki ketjun käsittelijät lipun EH_UNWINDINGkanssa siivoamaan (soita tuhoaja ) . [4] Jos mikään ohjelmoijan asettamista poikkeuskäsittelijän suodattimista ei palauttanut arvoa EXCEPTION_EXECUTE_HANDLER tai EXCEPTION_CONTINUE_EXECUTION, suoritetaan UnhandledExceptionFilter oletuspoikkeuskäsittelijän suodatin, joka rekisteröidään säiettä valmistautuessaan suorittamaan.

Käsittelijän kutsu

Poikkeuksen sattuessa käyttöjärjestelmä ei kutsu suoraan poikkeussuodatinta (joka vastaa siitä, käsitteleekö tietty käsittelijä tapahtuneen poikkeuksen vai ei), vaan välittää osoitteensa funktiolle _except_handler3, josta suodatintoiminto kutsutaan . Se käyttää seuraavaa tietorakennetta: [6]

struct _EXCEPTION_REGISTRATION { struct _EXCEPTION_REGISTRATION * prev ; void ( * käsittelijä )( PEXCEPTION_RECORD , PEXCEPTION_REGISTRATION , PCONTEXT , PEXCEPTION_RECORD ); struct Scopetable_entry * soveltamisalataulukko ; int trylevel ; int_ebp ; _ PEXCEPTION_POINTERS xpointers ; };

Kenttä *scopetableosoittaa rakennetaulukon osoitteeseen scopetable_entryja trylevel kokonaislukukenttä osoittaa tämän taulukon indeksiin. Kenttä _ebpsisältää pinokehysosoittimen arvon, joka oli olemassa ennen EXCEPTION_REGISTRATION-rakenteen luomista. [7] Toiminto _except_handler3kutsuu tarvittavan suodattimen ja ennen käsittelijän kutsumista purkaa (puhdistaa) pinon funktiolla ntdll.dll!RtlUnwind.

Jos mikään ohjelmoijan asentamista käsittelijöistä ei suostunut käsittelemään poikkeusta, kutsutaan toiminto UnhandledExceptionFilter, joka tarkistaa, onko prosessi käynnissä debuggerin alla ja ilmoittaa, onko se saatavilla. [7] Funktio kutsuu sitten oletuskäsittelijän suodatinta (jonka funktio asettaa SetUnhandledExceptionFilterja joka palauttaa aina EXCEPTION_EXECUTE_HANDLER). [7] Sitten, käyttöjärjestelmän asetuksista riippuen, kutsutaan joko debuggeri tai NtRaiseHardError-toiminto, joka näyttää virheilmoituksen. [7]

Muistiinpanot

  1. Strukturoitujen poikkeusten käsittely (Windows) . Haettu 5. toukokuuta 2010. Arkistoitu alkuperäisestä 25. syyskuuta 2010.
  2. Tietoja strukturoidusta poikkeuskäsittelystä (Windows) . Haettu 5. toukokuuta 2010. Arkistoitu alkuperäisestä 28. helmikuuta 2011.
  3. 1 2 Johdatus SEH Structured Exception Handlingiin (kuollut linkki) . Käyttöpäivä: 26. joulukuuta 2012. Arkistoitu alkuperäisestä 27. maaliskuuta 2014. 
  4. 1 2 WASM.IN Win32 SEH sisällä (osa 1) . Haettu 5. huhtikuuta 2018. Arkistoitu alkuperäisestä 5. huhtikuuta 2018.
  5. SEH:n käyttö Win32-ympäristössä . Haettu 1. toukokuuta 2010. Arkistoitu alkuperäisestä 24. syyskuuta 2015.
  6. WASM.IN Win32 SEH sisältä (osa 2) . Haettu 5. huhtikuuta 2018. Arkistoitu alkuperäisestä 5. huhtikuuta 2018.
  7. 1 2 3 4 WASM.IN Win32 SEH sisältä (osa 3) . Haettu 5. huhtikuuta 2018. Arkistoitu alkuperäisestä 5. huhtikuuta 2018.