![]() |
Wieso Speicheranforderung in Try...Finally ?
Hi Gemeinde,
Hier wird einem ständig empfohlen, Speicheranforderungen und -freigabe unbedingt immer in Try-Finally-Blöcke zu packen ("Resourcenschutzblöcke") Ich verstehe den Sinn nur bedingt. Natürlich ist es manchmal sinnvoll, aber eigentlich nur, um einen Securitylayer um eine Methode zu legen, à la:
Delphi-Quellcode:
Hier werden Exceptions einer tieferen Ebene so behandelt, das erstens die Methode nach außen hin keinen Schaden anrichtet und zweitens die sehr spezifischen Exceptions der tieferen Ebene in abstraktere Exceptions gemappt werden. Es interessiert z.B. den Anwender einer abstrakten Verbindungskomponente herzlich wenig, das die TCP/IP-Addresse nicht aufgelöst werden kann, schließlich weiß er gar nicht, das die Verbindung heute mal über TCP hergestellt wird.
Procedure TMyClass.QuiteAbstractMethod;
Begin helper := THelper.Create; Try Try helper.Perform; performSomethingMore; finally helper.free end; Except On E:Exception Do Begin UndoWhateverHappened; MapExceptionToAbstractLayer(E) End; End; End; Die Helper-Methode "Perform" wäre nach genau dem gleichen Muster gestrickt. Kennt jemand noch andere sinnvolle Beispiele, wo ein "Resourcenschutzblock" wirklich nötig ist? Versteht mich bitte nicht falsch, ich bau die Dinger seit Jahren automatisch ein, aber langsam nerven die Teile, denn sie machen den Code unübersichtlich und sind zum größten Teil überflüssig:
Delphi-Quellcode:
Ich meine, wenn es hier knallt, hab ich einfach etwas falsch gemacht. Im Umkehrschluss benötige ich also kein Try-Finally, wenn ich alles richtig gemacht habe.
Procedure TMyForm.Button1Click (Sender : TObject);
Var B : TSomething; Begin B := TSomething.Create; Try B.Work; Finally B.Free End End; Bevor man hier mit weiteren Beispielen kommt, bitte nachdenken, ob es sich nicht um o.g. Securitylayer-Implementierungen handelt... |
AW: Wieso Speicheranforderung in Try...Finally ?
Es geht primär um größere Anforderungen. Ich hatte schon das ein oder mal, wo das einfache Erzeugen einer Klasse mehr Speicher allokieren wollte (bzw. sogar musste), als das System zu diesem Zeitpunkt bereitstellen konnte. So ne OutOfMemoryException ist böse, wenn sie einem dann den kompletten Prozess abschiesst anstelle sauber abgefangen und behandelt zu werden.
Deswegen sollte man immer damit rechnen, dass die Anforderung des Speichers schief gehen kann. Wenn man damit leben kann, das einem in dem Fall die Anwendung wegbricht ist das okay. Ich will das sauber abgefangen haben ;-) |
AW: Wieso Speicheranforderung in Try...Finally ?
Ich habe das Gefühl, dass Dir der Sinn des Exception-Handlings nicht ganz klar ist. Es ist ja nicht dazu da, um Fehler, die Du durch Schusseligkeit eingebaut hast, zu beheben, sondern um Ausnahmen (eben Exceptions) abzuhandeln. Es befreit einen nicht von der Pflicht, ggf. unumgängliche Ausgangszustände im Vorfeld abzuchecken. Tritt innerhalb eines try-finally-Blocks eine Exception auf, wird ja der finally-Teil in jedem Fall durchlaufen (sogar, wenn ein exit drinsteht), der except-Teil aber nur im Ausnahmefall. Verzichtet man auf Ressourcen-Schutzblöcke, dann hat man eben im Fehlerfall das Dilemma, dass der Code zum Freigeben nicht mehr ausgeführt wird.
|
AW: Wieso Speicheranforderung in Try...Finally ?
Genau wie mit dem Anschnallen im Auto. Auch wenn man sich anschnallt, sollte man möglichst Unfälle versuchen zu verhindern. Und auch wenn man zu 90% unfallfrei fährt, sollte man sich doch anschnallen.
|
AW: Wieso Speicheranforderung in Try...Finally ?
In der Fachlogik nutze ich z.B. nur try..finally, und im finally wird nach Resourcenschutz und ggf. Undos die Exception wieder geraised. In der GUI bzw. GUI-nahen Teilen dagegen wenn möglich nur try..except, um ggf. entsprechende Meldungen ausgeben zu können. Der Resourceschutz sollte möglichst komplett in der Fachlogik passiert sein, ebenso will ich keine eine ShowMessage() aus diesen jemals sehen, denn da gehören sie nicht hin.
Sinn des finally ist halt eben genau das, wie es heisst: Resourcen schützen, sprich Speicherleichen vermeiden. |
AW: Wieso Speicheranforderung in Try...Finally ?
@FredlFesl
In mir hast Du einen Verbündeten. Aber Du musst Dich entscheiden, ob Du Dich mit dem Rest der DP-Welt anlegen willst :-D -> ![]() Würde mich dann auch mal interessieren, ob Du mein Anliegen nachvollziehen kannst (zu dem ich immer noch stehe: -> ![]() Ich würde das für ein sehr nützliches Sprach-Feature halten. Try-Finally-Blöcke haben auch ihren Nutzen, aber m.E. in anderen Anwendungsfällen. |
AW: Wieso Speicheranforderung in Try...Finally ?
Und die "Anforderung" gehört NICHT in den Schutzblock, sondern direkt davor.
Ausnahme: Die entsprechende Variable wird vorher initialisiert und am Ende überprüft+freigegeben. Geschützt (sicher freigegeben) werden die angeforderte Sachen, nach ihrer Anforderung und nicht die Anforderung selber, denn geht diese schief, gibt's ja auch nix zum Freigeben. |
AW: Wieso Speicheranforderung in Try...Finally ?
Zitat:
Nochmal: Ich weiss genau, wie Exceptions funktionieren und warum. Ich behaupte nur, das es nur diesen einen Fall für Try-Finally gibt und die Vorschläge (hier und in allen anderen Foren), GRUNDSÄTZLICH jedes "Free" in einen Finally-Block zu packen, Quatsch ist. Zitat:
@DeddyH: Ich meine z.B. deinen Beitrag #2 in ![]() Diese Regel "sollten immer"... ist overkill. Die Regel muss lauten: "Wenn Du einen reentranten Zustand wieder herstellen kannst, dann tu es". Wenn z.B. der Speicher begrenzt ist, und(!) es an der Stelle nicht weiter geht, kann ich mir Resourcenschutzblöcke echt sparen. Mit dem Beenden der Anwendung wird der Speicher eh freigegeben. Nochmal:
Code:
ist fast immer overkill.
MyStringList := TStringlist.Create;
Try MyStringList.Add('A lot of strings'); Finally MyStringList.Free; End; |
AW: Wieso Speicheranforderung in Try...Finally ?
Was aber, wenn das Programm ständig durchlaufen soll/muss? Ein Server vielleicht, oder eine Kontrollstation der Bahn?
Was passiert dann wohl, wenn sich das Program mal so eben verabschiedet? |
AW: Wieso Speicheranforderung in Try...Finally ?
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:52 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz