Programarea în Delphi

4.4. Protecția resurselor alocate de pierderi

Când programatorul după compilare primește un fișier gata de execuție, el crede cu sinceritate că programul va funcționa exact cum dorește. În timp ce se află în mâinile lui de îngrijire, se întâmplă de obicei. Când programul intră în condiții mai grave - la un utilizator nou și la alt computer - se poate întâmpla ceva. "Proprietarul nou" poate introduce litere în loc de numerele așteptate, extrage o rădăcină de la un număr negativ, împarte cu zero și efectuează multe alte erupții, adesea acțiuni aleatorii. Mai ales acest lucru se aplică aplicațiilor interactive (interactive), și astfel - marea majoritate. Din aceasta rezultă că programatorul trebuie să organizeze o apărare puternică împotriva tuturor violurilor asupra vieții programului său în procesul de implementare. Modul de realizare a acestui lucru este descris în acest capitol.







4.1. Erori și excepții

Ar trebui să știți că pot apărea erori în orice aplicație care rulează. Motivele pentru aceste erori sunt diferite. Unele dintre ele sunt subiective și provocate de acțiunile analfabete ale programatorului. Dar există și erori obiective, ele nu pot fi evitate în timpul proiectării programului, dar îl puteți găsi în timpul funcționării sale. Există multe exemple de astfel de erori: cantitate insuficientă de memorie liberă, nici un fișier pe disc, ieșirea valorilor datelor originale din intervalul admisibil etc.

Un program bun trebuie să facă față greșelilor sale și să lucreze fără să se închidă și să stea în orice circumstanță. Pentru a rezolva erorile, puteți, bineînțeles, să încercați să utilizați structurile formularului dacă apoi ieșiți. Cu toate acestea, în acest caz, algoritmul dvs. subțire și frumos pentru rezolvarea problemei principale va fi acoperit cu verificări urâte, astfel încât într-o săptămână să nu-i dați seama. Din acest impas aproape, mediul Delphi oferă o cale simplă și elegantă - mecanismul de tratare a excepțiilor.

Situația excepțională (excepție) este întreruperea cursului normal al programului din cauza imposibilității de a efectua în mod corect acțiunile ulterioare.

Mecanismul de tratare a excepțiilor este cel mai potrivit pentru interacțiunea programului cu biblioteca de subrutine. Rutinele bibliotecii detectează erori, dar în cele mai multe cazuri nu știu cum să reacționeze la ele. Programul apelant, dimpotrivă, știe ce să facă în caz de eroare, dar, de regulă, nu știe cum să le detecteze în timp. Datorită mecanismului de tratare a excepțiilor, biblioteca și programul care o utilizează sunt gestionate în timpul procesării erorilor.

Mecanismul de tratare a excepțiilor este destul de complex în implementarea sa, însă pentru programator este simplu și transparent. Pentru ao folosi, au fost introduse construcții de încercări speciale în limba Delphi. cu excepția. end. încercați. în cele din urmă. sfârșitul și declarația de ridicare. discutate în acest capitol.

4.2. Clasele de excepție

Situații excepționale în limba Delphi sunt descrise de clase. Fiecare clasă corespunde unui anumit tip de excepție. Când se produce o excepție în program, se creează un obiect din clasa corespunzătoare, care transferă informații despre această situație de la locul de origine la locația de procesare.

Clasele de excepție formează o ierarhie, a cărei rădăcină este clasa Excepție. Clasa Excepție descrie cel mai comun tip de excepție, iar moștenitorii săi sunt tipuri specifice de astfel de situații (Tabelul 4.1). De exemplu, clasa EOutOfMemory este generată de Excepție și descrie o situație în care RAM-ul liber este epuizat.

Următorul tabel prezintă clasele excepționale standard declarate în modulul SysUtils. Acestea acoperă aproape întreaga gamă de posibile erori. În cazul în care nu sunt încă suficiente, puteți declara clase de clase excepționale ridicate de la clasa Excepție sau de la moștenitorii săi.

Clasa de excepție

O excepție "silențioasă" folosită pentru a ieși din mai multe niveluri de blocuri sau subrutine imbricate. În același timp, pe ecran nu se afișează mesaje de eroare. Pentru a genera o excepție EAbort, trebuie să apelați procedura standard Abort.

A apărut o eroare la accesarea fișierului sau a dispozitivului I / O. Codul de eroare este conținut în câmpul ErrorCode.

O situație excepțională care apare în afara programului, de exemplu, în sistemul de operare.

O situație excepțională care a survenit în afara programului, de exemplu, într-o bibliotecă DLL dezvoltată în C ++.

O clasă generală de excepții care apare atunci când lucrați cu memorie dinamică. Este esențial pentru clasele EOutOfMemory și EInvalidPointer. Înțelegerea! Crearea unor situații excepționale din această clasă (și a tuturor descendenților săi) este complet acoperită de mediul Delphi, astfel încât să nu creați niciodată astfel de situații excepționale folosind operatorul de creștere.

RAM-ul liber este epuizat (a se vedea EHeadException).







Sa încercat eliberarea unui pointer nevalid (a se vedea EHeadException). De obicei, acest lucru înseamnă că pointerul este deja eliberat.

Clasa excepțională generală a aritmeticii întregi, din care se generează clasele EDivByZero, ERangeError și EIntOverflow.

Încercați să împărțiți un număr întreg cu zero.

Căutarea unui handler adecvat se efectuează secvențial până când clasa de excepție este compatibilă cu clasa specificată în instrucțiunea. Odată ce mânerul este găsit, operatorul din spatele cuvântului do este executat și controlul este trecut peste secțiunea excepțională. end. Dacă excepția nu se aplică niciuneia dintre clasele specificate, atunci controlul este trecut în blocul de încercare exterioară. cu excepția. capăt și căutatorul este căutat în el.

Rețineți că ordinea declarațiilor este semnificativă, deoarece recunoașterea excepțiilor trebuie să aibă loc de la clase private la clase comune, cu alte cuvinte, de la descendenți la strămoși. Care este motivul pentru aceasta? Acum veți înțelege. Imaginați-vă că modificați ordinea instrucțiunilor de pe exemplul de mai sus, dacă luați în considerare faptul că clasa EMathError este clasa de bază pentru EZeroDivide. Răspunsul este simplu: managerul EMathError va absorbi toate erorile din matematică reală, inclusiv EZeroDivide. în consecință, mânerul EZeroDivide nu va executa niciodată.

La cel mai înalt nivel al programului, este necesar să se intercepteze toate excepțiile, astfel încât, în cazul unei erori neînregistrate, aplicația să fie terminată corect. Pentru aceasta, se folosește așa-numitul procedurator de excepție implicit. Este scrisă în secțiunea excepțională după toate declarațiile și începe cu alt cuvânt cheie:

4.3.3. Exemplu de manipulare a excepțiilor

Ca exemplu de manipulare a excepțiilor, luați în considerare două funcții: StringToCardinal și StringToCardinalDef.

Funcția StringToCardinal convertește un șir la un tip cardinal. Dacă conversia nu este posibilă, funcția creează o excepție pentru clasa EConvertError.

Funcția StringToCardinalDef convertește, de asemenea, un șir la un tip cardinal, dar spre deosebire de funcția StringToCardinal, nu creează o excepție. În schimb, vă permite să specificați valoarea care este returnată în cazul unei încercări de conversie nereușite:

Pentru a converti șirul sursă la un număr, utilizați funcția StringToCardinal definită mai sus. Dacă se produce o excepție în timpul conversiei, aceasta este "absorbită" de funcția StringToCardinalDef, care în acest caz returnează valoarea parametrului Default. Dacă există o altă eroare (nu EConvertError), atunci controlul este transmis blocului extern de tratare a excepțiilor din care a fost apelată funcția StringToCardinalDef.

Exemplul este foarte simplu, dar demonstrează avantajele situațiilor excepționale înainte de tratarea tradițională a erorilor. Imaginați-vă calcule mai complexe, constând dintr-un set de operatori, în fiecare dintre care poate apărea o eroare. Cât de dificil va fi manipularea erorilor prin afirmații multiple și dacă simpla încercare este.

4.3.4. Reluarea unei situații excepționale

În cazurile în care un bloc protejat nu poate face față excepției în întregime, acesta efectuează numai partea sa din lucrare și reia excepția, astfel încât prelucrarea să continue cu blocul protejat extern:

Dacă niciunul dintre blocurile externe protejate nu a procesat excepția, controlul este transmis procesatorului de excepție standard care încheie aplicația.

4.3.5. Accesați obiectul care descrie excepția

Excepția de manipulare poate necesita acces la un obiect care descrie această situație și conține un cod de eroare, o descriere text a erorii și așa mai departe. În acest caz, se folosește înregistrarea operatorului extins:

Variabila E este un obiect excepțional, ShowMessage este procedura pentru modulul DIALOGS, afișând o fereastră mică cu text și un buton OK de pe ecran. Proprietatea Mesaj pentru șir este definită în clasa Excepție. conține o descriere textuală a erorii. Valoarea inițială pentru textul mesajului este specificată la construirea obiectului de excepție.

Rețineți că, după manipularea excepției, eliberarea obiectului corespunzător este efectuată automat, nu este necesar să faceți acest lucru.

4.4. Protecția resurselor alocate de pierderi

4.4.1. Scurgerea resurselor și protecția acestora

Programele construite folosind mecanismul de exceptare trebuie să respecte reguli stricte pentru alocarea și eliberarea de resurse, cum ar fi memoria, fișierele, resursele sistemului de operare.

Imaginați-vă o situație: o subrutină distribuie o anumită resursă, dar o excepție oprește executarea acesteia, iar resursa rămâne ne-eliberată. Chiar și să credem că este teribil, ceea ce poate duce la o astfel de eroare: o scurgere de memorie, descriptori de fișiere, alte resurse ale sistemului de operare. Prin urmare, resursele trebuie protejate de situații excepționale. Pentru aceasta, există o altă variantă a blocului protejat în mediul Delphi:

Particularitatea acestui bloc este faptul că în cele din urmă secțiune. sfârșitul este executat întotdeauna indiferent dacă apare sau nu excepția. Dacă există o declarație a secțiunii de încercare. În cele din urmă generează o excepție, secțiunea finală este executată pentru prima dată. end. numit secțiunea de completare (eliberarea de resurse), iar apoi controlul este transferat către un bloc protejat extern. Dacă toți operatorii protejați sunt executați fără erori, atunci și secțiunea de terminare funcționează, dar controlul este transferat operatorului care îl urmărește. Rețineți că în cele din urmă secțiune. sfârșitul nu se ocupă de excepție, nu are mijloacele de a detecta, și nici nu are acces la obiectul excepțional.

Programarea în Delphi

Figura 4.2. Logica încercării ... cu excepția ... declarației finale

Blocul de încercare. în cele din urmă. sfârșitul are încă o caracteristică importantă. Dacă este plasat într-o buclă, atunci apelarea din blocul de procedură protejat Break pentru a ieși prematur din bucla sau procedura Continuare pentru a trece la următoarea iterație a bucla mai întâi asigură că secțiunea finală este executată. end. și apoi tranziția corespunzătoare este deja efectuată. Această declarație este valabilă și pentru procedura Exit (ieșire din subrutină).

După cum arată practica, subrutinele deseori distribuie mai multe resurse simultan și le folosesc împreună. În astfel de cazuri, se utilizează blocuri de încercare imbricate. în cele din urmă. end:

În plus, puteți combina cu succes blocurile de încercare. în cele din urmă. terminați și încercați. cu excepția. pentru protecția resurselor și tratarea excepțiilor.

4.5. rezultate

În acest capitol, ați învățat multe despre situații excepționale și modalități de abordare a acestora. Acum, programele dvs. vor da cu siguranță o rebutură demnă nu numai pentru cel mai brut utilizator, ci și pentru computerul său din lemn. Acest lucru, apropo, este una dintre calitățile necesare care vă va permite să vă clasificați programul ca o clasă bună. Să ne reamintim, de asemenea, că aici s-au luat în considerare doar erorile de execuție, deci nu uitați să citiți Capitolul 10, care discută despre lupta împotriva erorilor logice.







Articole similare

Trimiteți-le prietenilor: