Bruke prøve ... endelig å unngå ressurs leaks

Denne artikkelen drøfter Delphi try..finally konstruere, når man skal bruke, og hvordan Castalia gjør det enklere å bruke.
(Opprinnelig publisert på delphi-expert.com på 16 mars 2004 )
I en bransje som har meg å undersøke en rekke kildekoden, jeg noen ganger merke vanlige vaner og trender i folks kode. Noen ganger er disse vaner er bra, som å bruke påstander. Noen ganger vaner er dårlige, som å bruke etiketter og GOTO. Noen ganger, er koden bare mangler noen veldig viktige elementer, enten på grunn av latskap eller utilstrekkelig forståelse på den delen av den som skrev koden. En av disse konstruksjonene som er veldig kraftig, men ofte neglisjert og noen ganger misbrukt, er Delphi " prøve " konstruere. I løpet av de neste to ukene, skal vi se på hva disse konstruerer gjøre og hvordan du bruker dem godt, og hvordan Castalia kan hjelpe deg å bruke dem effektivt og ikke overse dem.
Denne uken vil vi konsentrere oss om forsøk ..finally konstruere. Neste uke vil vi gå i detalj med try..except, inkludert noen historie på konseptet unntak. Vi vil også gjøre narr av java, som kan lære oss mye med sin over-the-top unntak håndtering mekanisme.
Innledning
Noen ganger må du sørge for at visse ting er gjort for å fullføre en oppgave, uavhengig av feil som kan ha oppstått i gjennomføringen av oppgaven. For eksempel, hvis en rutine tar kontroll av en ressurs, er det vanligvis nødvendig for rutinemessig å frigjøre ressursen selv om det oppstår feil i prosessen. For eksempel i følgende kode, er en fil F åpnet, litt tekst er skrevet til den, og da er det stengt. . Sviktende å lukke filen vil resultere i en ressurslekkasje, og vil være en førsteklasses bug
Reset (F), WriteLn (F, "Hello, World! '); CloseFile (F),
Denne koden fungerer helt fint så lenge hver funksjon utfører normalt, men hvis noe unormalt skjer, så vil det bli bråk. For eksempel, hvis Reset (F) er vellykket, men for noen grunn kallet til WriteLn mislykkes, rutinen vil avslutte uten noen gang å forsøke å CloseFile (F). Som et resultat, vil filen aldri bli stengt, og en ressurs har blitt lekket.
Hvordan løser vi dette problemet? WriteLn gir ikke noen feilkontroll mekanisme som noen rutiner gjør (mer om det i neste uke). Det bare utfører, og hvis noe går galt, reiser det et unntak (mer om det i neste uke også). I et nøtteskall, er et unntak en unormal tilstand i utførelsen av et program som gjør at flyten av programmet for å bli avbrutt. Det vi trenger er en måte å sørge for at CloseFile (F) blir kalt selv om et unntak oppstår. Dette er akkurat hva den try..finally konstruksjonen er for. Vurdere den samme koden, men med den beskyttede flytkontroll av en prøve-endelig blokk:
Reset (F); prøve
WriteLn; endelig <(F, "Hello, World!") br> CloseFile (F); end
;
Nå har vi sørget for at CloseFile (F) vil bli kalt uansett hva som skjer under samtalen til WriteLn. Nå for en mer formell definisjon, rett fra Delphi hjelp:
syntaksen til en try..finally utsagn er
prøve statementList1
endelig statementList2
slutten
der hvert statementList
er en sekvens av utsagn avgrenset med semikolon. Den try..finally uttalelse utfører uttalelsen i statementList1 plakater (try klausul). Hvis statementList1
ferdig uten å heve unntak, blir statementList2 plakater (den endelig klausul) henrettet. Hvis et unntak er hevet under kjøring av statementList1
, kontroll er overført til statementList2
; gang statementList2
ferdig utførende, unntaket er høynet. Hvis en samtale til Exit
, Break
, eller Fortsett
prosedyre årsaker kontrollere forlate s tatementList1
, statementList2 Anmeldelser utføres automatisk. Dermed endelig klausulen er alltid utført, uavhengig av hvordan prøve klausul opphører.
Nå som vi har en forståelse av try..finally konstruere og når man skal bruke det, la oss se på hvordan Castalia kan hjelpe.
Kode Maler
Castalia gir en rekke kode maler som involverer try..finally konstruere. Når først installert, Castalia omfatter Tryf og trycf maler. Den Tryf malen oppretter et enkelt skjelett for en prøve blokk. For å bruke Tryf mal, bare skrive " Tryf " i editoren og dytte på mellomromstasten. Skjelett koden vil bli satt inn:
prøve Anmeldelser | endelig
| end
;
markøren vil bli plassert på riktig sted i prøve klausulen . Når du har opprettet koden i prøve klausulen, trykker du én gang hoppe inn i endelig klausulen. Deretter oppretter din opprydding kode.
Trycf mal løser et spesielt vanlig bruk av try..finally konstruere i Delphi. Dette er den dynamisk opprettelse og ødeleggelse av objekter. Dårlig eksempel:
MyStrings: = TStringList.Create;MyStrings.Add('Hello');MyStrings.Add('World');MyStrings.SaveToFile('hello.txt');MyStrings.Free;
This er lik det første eksempel. En ressurs (minne) blir tildelt - i dette tilfellet av en konstruktør. Ressursen blir manipulert, så resoruce er deallocated av kallet MyStrings.Free. Hvis vi ikke kalle MyStrings.Free, ville minnet bli deallocated, og vi vil være å se på enda en ressurs lekkasje. Igjen, er problemet det samme. Hvis noe går galt når manipulere minnet, destructor aldri ringte og minnet er aldri deallocated. Her er den riktige koden:
MyStrings: = TStringList.Create; prøve
MyStrings.Add ('Hello'); MyStrings.Add ('World'); MyStrings.SaveToFile ('hello.txt'); endelig
MyStrings.Free; end
;
merke til at MyStrings.Free har blitt flyttet inn i endelig
klausul, slik at uansett hva som skjer i prøve-leddet, vil objektet bli frigjort. Castalia sin trycf mal gir et skjelett for denne konstruksjonen. For å bruke trycf malen, skriv " trycf " i redigeringsprogrammet og trykker på mellomromstasten. Skjelett koden vil bli satt inn:
| : = | .Create; prøve Anmeldelser | endelig
| .Gratis; end
;
markøren vil bli plassert der den første | karakter er, og trykke vil hoppe til hver | i orden. (De | tegnene vises ikke i kode, men benyttes her for tydelighets skyld). Du bør bruke trycf malen når du oppretter objekter dynamisk.
Du kan lære mer om Castalia sin kode maler her
. Refactoring
Kode maler er nyttig når vi skriver nye koden, men hjelper ikke veldig mye når vi skal endre eksisterende kode i samsvar med vår nye forståelse av try..finally. Castalia sin refactorings vil hjelpe med det. &Quot; Surround Med ... " refactoring lar deg velge en blokk med kode og plassere en try..finally blokk rundt det med bare noen få museklikk. Bare velg den koden som går i prøve-leddet og klikk med høyre museknapp. Fra " Refactoring " menyen, velg " Surround Med ... " og til slutt velge ". try..finally " Koden vil bli umiddelbart innrykket og omsluttet av en skikkelig try..finally blokk.
Du kan lære mer om Castalia automatiserte refactoring fasiliteter her.
Denne uken har vi lært å bruke Delphi try..finally konstruere å unngå ressurs lekkasjer og andre flyt kontroll problemer. Vi har også lært hvordan Castalia kan hjelpe oss til å bruke denne konstruksjonen mer effektivt med både ny kode og eksisterende kode. Neste uke vil vi se på try..except og lære hvordan Castalia kan hjelpe oss å skrive bedre avvikshåndtering kode. Anmeldelser