| Autor |
Beitrag |
AScomp
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: Di 05.01.10 07:51
Guten Morgen,
mit try..except kann ich im Normalfall ja das Auslösen bzw. die Anzeige von Exceptions verhindern. Bisher ging ich davon aus, dass
Delphi-Quelltext 1: 2: 3: 4:
| try bla; except end; |
wirklich ALLE möglicherweise beim Aufruf von "bla" auftretenden Exceptions abgefangen werden und der Programmablauf nicht abgebrochen wird.
In einem anderen Forenbereich hatte ich jetzt von einem Problem mit folg. Sourcecode berichtet:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| try if CreateLogfile then begin AssignFile(LogDatei, AppDataDir + 'mk.log'); if FileExists(AppDataDir + 'mk.log') then Append(LogDatei) else ReWrite(LogDatei); WriteLn(LogDatei, Info); end; finally try CloseFile(LogDatei); except end; Application.ProcessMessages; end; |
Trotz try..finally wurde nämlich beim Aufruf von "Append(LogDatei)" eine Exception ausgelöst, die von madExcept behandelt wurde.
Inzwischen hab ich die entsprechenden, möglicherweise auftretenden Exceptions in obigem Sourcecode durch den Schalter {$I-} erstmal deaktiviert.
Dann noch folgender Fall:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| try FormProgress.VCLZipVerify.ReadZip; FormProgress.VCLZipVerify.CheckArchive; except On EUserCanceled do ExecutionCancelled := true; end; |
Ich ging bisher anscheinend fälschlicherweise davon aus, dass mit diesem Sourcecode alle Exceptions abgefangen werden und nur im Falle der Exception EUserCancelled die Variable noch auf true gesetzt wird.
Doch anscheinend ist das falsch. Der obige Sourcecode fängt nur eine einzige Exception ab, eben EUserCancelled. Alle weiteren Exceptions bleiben unbehandelt und werden normal ausgegeben. Um das zu verhindern, müsste ich wohl den Sourcecode wie folgt abändern:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| try FormProgress.VCLZipVerify.ReadZip; FormProgress.VCLZipVerify.CheckArchive; except On EUserCanceled do ExecutionCancelled := true; else end; |
Doch was heißt das jetzt genau für:
Delphi-Quelltext 1: 2: 3: 4:
| try bla; except end; |
Heißt das, dass in diesem Beispiel ALLE Exceptions abgefangen werden (da im except-Abschnitt keine Exception explizit behandelt wird)? Und würde sich das Verhalten ändern, sobald ich im except-Abschnitt ein on EIrgendwas do einfüge (nämlich derart, dass nur noch diese eine Exception abgefangen wird, während alle anderen unbehandelt bleiben und entsprechend auch vom Programm ausgegeben werden?)?
Danke schonmal, falls jemand meinen Ausführungen überhaupt folgen konnte - wurde ja ein richtiger Roman. 
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 05.01.10 10:46
|
|
AScomp 
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: Di 05.01.10 12:32
Das ist soweit klar - danke!
|
|
jakobwenzel
      
Beiträge: 1889
Erhaltene Danke: 1
XP home, ubuntu
BDS 2006 Prof
|
Verfasst: Di 05.01.10 15:19
AScomp hat folgendes geschrieben : | | Trotz try..finally wurde nämlich beim Aufruf von "Append(LogDatei)" eine Exception ausgelöst, die von madExcept behandelt wurde |
Das soll auch so, try...finally ist dazu da um etwas (beispielsweise das Freigeben von Objekten) auch dann durchzuführen wenn eine Exception auftrat. Gefangen wird die Exception nur im try...except.
_________________ I thought what I'd do was, I'd pretend I was one of those deaf-mutes.
|
|
AScomp 
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: Di 05.01.10 15:34
jakobwenzel hat folgendes geschrieben : | AScomp hat folgendes geschrieben : | | Trotz try..finally wurde nämlich beim Aufruf von "Append(LogDatei)" eine Exception ausgelöst, die von madExcept behandelt wurde |
Das soll auch so, try...finally ist dazu da um etwas (beispielsweise das Freigeben von Objekten) auch dann durchzuführen wenn eine Exception auftrat. Gefangen wird die Exception nur im try...except. |
Sicher? Ich bezweifle, dass es so ist. Im Beitrag www.delphi-forum.de/...ryfinally_96919.html kam das auch so rüber, als ob finally eher die Exception "schlucken" würde.
Demzufolge müsste man dann except und finally auch gemeinsam nutzen können.
Also beispielsweise sowas:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| try if CreateLogfile then begin AssignFile(LogDatei, AppDataDir + 'mk.log'); if FileExists(AppDataDir + 'mk.log') then Append(LogDatei) else ReWrite(LogDatei); WriteLn(LogDatei, Info); end; except finally try CloseFile(LogDatei); except end; Application.ProcessMessages; end; |
Sprich: Wenn im try-Abschnitt eine Exception auftritt, soll diese "geschluckt" werden und der finally-Abschnitt abgearbeitet werden.
|
|
JDF
      
Beiträge: 29
WinNT, Win2k, WinXP, Win2003
d6ent, d7pro, bds2006ent, vs2003
|
Verfasst: Di 05.01.10 15:54
Hi,
| Zitat: | | Demzufolge müsste man dann except und finally auch gemeinsam nutzen können. |
ist eine schöne Idee, andere Programmiersprachen können das.
Im Delphi kenne ich nur die Schachtelung von try..except und try..finally.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure Test; begin TRY Objekt.Erstellung; TRY TRY Objekt.Nutzung; EXCEPT Objekt-Anhängige Fehlerbearbeitung; END; FINALLY Objekt.Beendigung; END; EXCEPT Objekt-Unabhängige Fehlerbearbeitung; END; end; |
Ohje, der Konstrukt sieht schlimm aus.
Gruß
Jürgen
|
|
AScomp 
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: Di 05.01.10 16:04
|
|
jakobwenzel
      
Beiträge: 1889
Erhaltene Danke: 1
XP home, ubuntu
BDS 2006 Prof
|
Verfasst: Di 05.01.10 16:10
Wenn hier aber in der Objekt-Anhängigen Fehlerbearbeitung nochmal ne Exception auftritt hast du ein nicht freigegebenes Objekt.
_________________ I thought what I'd do was, I'd pretend I was one of those deaf-mutes.
|
|
AScomp 
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: Do 11.03.10 20:42
Hallo,
hätte nochmal eine Frage hierzu:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| function _GetFileSize(const FileName: string): Int64; var FileStream: TFileStream; begin Result := -1; try try FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone); Result := FileStream.Size; except end; finally try FileStream.Free; except end; end; end; |
Geht das nicht einfacher?
Ein
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| try .. except .. finally .. end; |
gibt's ja anscheinend nicht.
Wie löse ich also obige Mini-Funktion sauber?
Das try..finally bräuchte ich ja eigentlich nicht, da ich die Exceptions ohnehin fange und der zweite try..except-Block somit ja in jedem Fall aufgerufen wird, richtig?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| function _GetFileSize(const FileName: string): Int64; var FileStream: TFileStream; begin Result := -1; try FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone); Result := FileStream.Size; except end; try FileStream.Free; except end; end; |
Sieht auch nicht viel besser aus.
Vielen Dank!
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Do 11.03.10 20:58
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| function _GetFileSize(const FileName: string): Int64; var FileStream: TFileStream; begin Result := -1; try FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone); try Result := FileStream.Size; finally FileStream.Free; end; except end; end; |
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
AScomp 
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: Do 11.03.10 21:13
Danke dir, das hatte ich auch schon - was mich stört ist, dass es zwei try-Blöcke sind.
Aber da es keine try..except..finally-Blöcke zu geben scheint, wird das wohl die einzige Möglichkeit sein.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 11.03.10 21:24
|
|
AScomp 
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: Do 11.03.10 21:29
Warum? Ich möchte ja, dass keine Exception angezeigt wird.
Wenn in deinem Beispiel der FileStream nicht erstellt werden kann, wird trotzdem der finally-Abschnitt aufgerufen und versucht, den FileStream wieder freizugeben.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 11.03.10 21:46
dann so rum:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| try <Resource belegen> try <Mit der Resource arbeiten> finally <Resource freigeben> end; except <Ausnahme behandeln> end; |
Aber was für ein Grund gibt es einen aufgetretenen Fehler unterdrücken zu wollen? Der Benutzer wäre über eine aussagekräftige Fehlermeldung bestimmt sehr erfreut, als einfach so im dunklen stehen gelassen zu werden und eventuell einen Datenverlust zu erleiden.
|
|
AScomp 
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: Do 11.03.10 21:51
Dass ich die Exception DORT nicht abfange heißt ja nicht, dass sie überhaupt nicht abgefangen wird. Nur eben nicht an dieser Stelle.
So hat es BenBe doch vorgeschlagen, oder entgeht mir schon wieder was? 
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 11.03.10 22:10
Mist, stimmt. Ich schiebe das jetzt mal auf meine Kopfschmerzen.
|
|
AScomp 
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: Do 11.03.10 22:11
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 12.03.10 01:23
@Luckie: Die Fehlerbehandlung wird in dieser Routine basierend auf dem Result erledigt. Sauberer wäre es aber mit CreateFile die Datei zu öffnen und über das Handle wenn möglich einen THandleStream aufzubauen. Wobei man für diesen Fall auch gleich komplett über die WinAPI gehen könnte, was sogar die Nutzung einer Exception hier ganz vermeidet ...
P.S.: Sollte man schlafen gehen, wenn man im vorigen Post "Gute Bescherung" liest?
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Fr 12.03.10 03:34
Die Kombination CreateFile/GetFileSizeEx/CloseHandle ist an der Stelle tatsächlich vorzuziehen.
Allein schon, weil man dann volle Kontrolle über Fehlercodes hat, und außerdem um den Aufwand der Klasseninstantiierung herum kommt.
P.S.: Ja, direkt bis zum Dezember durchschlafen...
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
|