AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Wieso Speicheranforderung in Try...Finally ?

Ein Thema von FredlFesl · begonnen am 12. Aug 2011 · letzter Beitrag vom 16. Aug 2011
Antwort Antwort
Seite 1 von 2  1 2      
FredlFesl

Registriert seit: 19. Apr 2011
293 Beiträge
 
Delphi 2009 Enterprise
 
#1

Wieso Speicheranforderung in Try...Finally ?

  Alt 12. Aug 2011, 19:07
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:
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;
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.

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:
Procedure TMyForm.Button1Click (Sender : TObject);
Var
  B : TSomething;

Begin
  B := TSomething.Create;
  Try
    B.Work;
  Finally
    B.Free
  End
End;
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.

Bevor man hier mit weiteren Beispielen kommt, bitte nachdenken, ob es sich nicht um o.g. Securitylayer-Implementierungen handelt...
Das Bild hängt schief.
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.643 Beiträge
 
#2

AW: Wieso Speicheranforderung in Try...Finally ?

  Alt 12. Aug 2011, 19:15
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
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
FredlFesl

Registriert seit: 19. Apr 2011
293 Beiträge
 
Delphi 2009 Enterprise
 
#3

AW: Wieso Speicheranforderung in Try...Finally ?

  Alt 12. Aug 2011, 21:39
Es geht primär um größere Anforderungen...
Wenn das der Fall ist, kann die Applikation sowieso nicht weiterlaufen. Und wenn nicht, tritt wieder mein bisher einziger Fall ein, bei dem ein Try-Finally Sinn macht, nämlich einen Security-Layer/Wrapper. Hier nach dem Motto: "Schaun mer mal, obs reicht. Wenn nicht, dann eben nicht". Hier würde der EOutOfMemoryException in eine andere Exception gemappt werden bzw. würde das komplett transparent gehandhabt werden.

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.

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.
Aber beim Unfall ist die Fahrt doch vorbei... Verstehst Du? Tritt ein Fehler auf, gehts eh nicht weiterm AUSGENOMMEN mein Beispiel.

@DeddyH: Ich meine z.B. deinen Beitrag #2 in http://www.delphipraxis.net/162202-s...ring-list.html

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:
MyStringList := TStringlist.Create;
Try
  MyStringList.Add('A lot of strings');
Finally
  MyStringList.Free;
End;
ist fast immer overkill.
Das Bild hängt schief.
  Mit Zitat antworten Zitat
WM_CLOSE

Registriert seit: 12. Mai 2010
Ort: königsbronn
398 Beiträge
 
RAD-Studio 2009 Pro
 
#4

AW: Wieso Speicheranforderung in Try...Finally ?

  Alt 12. Aug 2011, 21:43
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?
Delphi programming
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#5

AW: Wieso Speicheranforderung in Try...Finally ?

  Alt 12. Aug 2011, 21:46
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.
Aber beim Unfall ist die Fahrt doch vorbei... Verstehst Du? Tritt ein Fehler auf, gehts eh nicht weiterm AUSGENOMMEN mein Beispiel.
Nicht wenn dein Leben das Programm ist, dann würdest du wahrscheinlich auch sehr darauf bedacht sein, dass du nach dem Unfall weiterlebst.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.351 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Wieso Speicheranforderung in Try...Finally ?

  Alt 12. Aug 2011, 22:03
@FredFesl

So selbstbewußt hätte ich es nicht vortragen können, sehe das aber genau so.
Ansonsten müsste man (wenn man es genau machen wollte) beim Erzeugen von 10 Objekten nacheinander auch 10 verschachtelte Schutzblöcke erzeugen (für jedes Objekt einen).
Es kann ja jeder machen wie er will, aber der Sinn erschließt sich mir (in den meisten Fällen) nicht.


@WM_CLOSE+Luckie

Wenn ein Programm mit einem solch gravierenden Fehler wochenlang durchläuft, ist mit dem Ergebnis wohl ohnehin nix anzufangen.
Das gilt jedenfalls, wenn der Fehler nicht komplett bereigit wird (incl. aller Daten und Zustände).
Und diese Bereinigung kann man eigentlich nur gewährleisten, wenn man mit einem bestimmten Fehler rechnet, den man aber nicht unbedingt vermeiden kann (E/A-Funktionen).
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.312 Beiträge
 
Delphi 12 Athens
 
#7

AW: Wieso Speicheranforderung in Try...Finally ?

  Alt 12. Aug 2011, 22:23
Ich sage es mal so "schau dir meinen FileSplitter (hier in der DP) mal an.
weiter siehe *1


Ja, wenn nach einem Knall (Exception) sowieso alles zu spät ist, könnte man es auch gleich sein lassen ... Windows räumt ja auf.

Aber dennoch sollte man es in einem gewissen Maße machen, denn wenn man etwas immer gleich macht, egal ob das Programm wichtig oder nutzlos ist, dann hat man a) ähnliche Programmstrukturen (Wiederverwendbarkeit) und damit auch ein leichteres Arbeiten, da man sich nur an eine Struktur halten muß, was auch das Lesen/Verstehen vereinfacht
und wenn man dann durch das viele Programmieren dieses total verinnerlicht hat, dann kann man es an wichtigen stellen nicht so schnell vergessen.



*1 Ja, auch ich schreibe schonmal Programme ganz ohne Try-Finally, denn unter gewissen Umständen ist sowas garnicht nötig, da z.B. die WinAPI an vielen Stellen mit Fehlercodes arbeitet und nicht mit Exceptions.
Wenn es dort Probleme gibt, dann werden diese nicht gleich mit einer Exception quitiert und man kann/muß diese Fehler dann anderes behanden. (knallt es dort wirklich mal mit einer Exception durch, dann ist sowieso alles zu spät und jede weitere Bemühung eher umsonst)


Mit genügend Wissen/Erfahrung kennt man gewisse Schwachstellen oder auch Ecken, wo eigentlich nie was schief laufen kann ... in soeinem Kall kann man die Fehlerbehandlung auch schonmal etwas "anpassen".

Aber im Normalfall sollte man einfach alles Schützen, wenn man weiß ja nie was mal passiert ... ganz besonders bei Codes, welche man anderen zur Verfügung stellt.
siehe http://www.delphipraxis.net/162202-s...ml#post1116391
Das Original hieß
Delphi-Quellcode:
Result := '';
Parse := TStringList.Create;
Row := TStringList.Create;
try
  Parse.Text := GetBarcodesResult;
Was eigentlich auch schon sicher genug ist. (siehe meine Erklärung dort drüben)
Aber dennoch, ein gewisser (ausreichender) Schutz wird dennoch verbaut, auch wenn einige meinen könnten "wozu ... ist doch eh umsonst?".
Denn weißt du, ob der Code nicht mal in einem wichtigen Programm verbaut würde?
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (12. Aug 2011 um 22:32 Uhr)
  Mit Zitat antworten Zitat
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#8

AW: Wieso Speicheranforderung in Try...Finally ?

  Alt 13. Aug 2011, 08:01
Ansonsten müsste man (wenn man es genau machen wollte) beim Erzeugen von 10 Objekten nacheinander auch 10 verschachtelte Schutzblöcke erzeugen (für jedes Objekt einen).
Verstehe ich nicht, in dem Thread "Bitte Warning erklären" wurden doch bereits Lösungen gezeigt, wie man die Verschachtelungen vermeiden kann. Auch die Behauptung "Wenn eine Exception auftritt, kann man alle weiteren Berechnung danach vergessen" stimmt doch so pauschal nicht. Das hängt doch stark von dem Kontext ab. Programme der Kategorie 24/7 haben da sicherlich andere Ansprüche, als ein Kommandozeilentool, dass nur mal schnell für eine spezifische Aufgabe zusammen gestrickt wurde.

Bei mir ist es eigentlich eher umgekehrt. Wenn in meinen Quelltext mal ein Schutzblock fehlt, dann ist das bei einer späteren Inspektion des Quelltextes immer ein Punkt, bei dem ich dann u.U. länger nachdenke, ob das an dieser Stelle tatsächlich legitim ist. D.h. ich verwende eventuell mehr Zeit bei der Wartung eines Quelltextes, wenn der Schutzblock fehlt, als wenn ich ihn konsequent einbaue.

D.h. der Schutzbock um "b.work" in dem Eingangs genannten Beispiel ist schon deshalb sinnvoll, weil ich bei der Wartung nicht in b.work reingehen muss um zu prüfen, ob da auch wirklich keine Exception auftreten kann.

Impliziert das Wort "Schutzblock" nicht schon, dass es sich um einen Security-Layer handelt? Und nein, ich kann mir keinen anderen sinnvollen Einsatz von Try-finally-Blöcken vorstellen, als genau diesen. Letztendlich ist es also die Frage, will ich auf Nummer sicher gehen, oder glaube ich, dass ich und alle anderen Verkehrsteilnehmer so gut sind, das niemals ein Unfall passieren kann (bzw. die Konsequenzen eines Unfalls sind mir einfach egal). Das muss jeder für sich entscheiden.
  Mit Zitat antworten Zitat
FredlFesl

Registriert seit: 19. Apr 2011
293 Beiträge
 
Delphi 2009 Enterprise
 
#9

AW: Wieso Speicheranforderung in Try...Finally ?

  Alt 13. Aug 2011, 09:41
...Nicht wenn dein Leben das Programm ist, dann würdest du wahrscheinlich auch sehr darauf bedacht sein, dass du nach dem Unfall weiterlebst.
Da haben wir es!
Wenn "mein Leben" das Programm ist, dann benötige ich den Sicherheitsgurt, denn das Fahren ist nur eine Aktion, die kontrolliert schiefgehen können muss.

Ist "die Fahrt" mein Programm, dann muss ich mich nicht anschnallen. Peng => Programm-Neustart. Wieso muss ich einen Sicherheitsgurt tragen, wenn ich bei einem Unfall sowieso von Vorne anfange?


Zitat:
... ist fast immer overkill.
Hm... diese Aussage ist ziemlich zweckfrei. Wenn du 6 Zeilen sinnlosen Code nimmst, bringt dich die Aussage, dass 3 davon überflüssig sind auch nicht weiter.
Eben doch. Der code ist nicht sinnlos, sondern aus einem Beitrag, in dem die Verwendung der TStringlist erklärt wurde. In [b]diesem[b/] Schnippsel ist Try-Finally überflüssig.

Zitat:
Aber du suchst ja nach einer Erklärung warum "immer" try-finally verwenden sollte.
1. Grund. Warum denn nicht?
Stimmt, aber es ist überflüssig. Aber guter Code ist minimalistisch. Aus dem gleichen Grund verwende ich "FreeAndNil" nicht. Ich will in meinem Code nicht gefragt werden: "Wieso machst Du das denn hier? Das ist überflüssig"
Anderes Beispiel: Grundsätzlich eine Variable initialisieren: Stört nicht, wird eh wegoptimiert und ist robust. Und überflüssig und blöd.
Zitat:
2. Grund: Lesbarkeit
Finde ich im Code eine Stelle an der eine Resource belegt oder ein Objekt erzeugt wird, will ich sofort als nächstes wissen wo die Freigabe ist. Ein try-finally ist da eine schöne Klammer die mich zu der Stelle mit der Freigabe führt.
Wieso ist es wichtig, wo die Freigabe erfolgt? Ist doch komplett egal (außer, ich suche ein Speicherleck). Bei C# und Java suchst Du dich i.A. ja auch blöd, um die Freigabe eines Objektes zu finden.
Zitat:
Zeig doch mal eine Code-Stelle aus einem deiner Programmen wo dich so ein try-finally so richtig nervt.
Delphi-Quellcode:
  f := TFoo.Create;
  Try
    b := TBar.Create
    Try
      b.DoSomething();
      f.Work();
    Finally
      b.Free
    End
  Finally
    f.free;
  End;
// --- vs
  
  f := TFoo.Create;
  b := TBar.Create
  b.DoSomething();
  f.Work();
  b.Free
  f.free;
Das Bild hängt schief.
  Mit Zitat antworten Zitat
HeZa

Registriert seit: 4. Nov 2004
Ort: Dortmund
182 Beiträge
 
Delphi 10 Seattle Professional
 
#10

AW: Wieso Speicheranforderung in Try...Finally ?

  Alt 13. Aug 2011, 11:28
Prima, jetzt werden wir konkret
Delphi-Quellcode:
  f := TFoo.Create;
  Try
    b := TBar.Create
    Try
      b.DoSomething();
      f.Work();
    Finally
      b.Free
    End
  Finally
    f.free;
  End;
// --- vs
  
  f := TFoo.Create;
  b := TBar.Create
  b.DoSomething();
  f.Work();
  b.Free
  f.free;
also das würde ich schon mal umbauen zu:
Delphi-Quellcode:
  b := TBar.Create;
  try
    b.DoSomething();
  finally
    b.Free
  end

  f := TFoo.Create;
  try
    f.Work();
  finally
    f.free;
  end;
und wenn ich diesen Code sehe ...
Delphi-Quellcode:
  f := TFoo.Create;
  b := TBar.Create
  b.DoSomething();
  f.Work();
  b.Free;
  f.free;
sehe ich 2 potenzielle Speicherlöcher. Um sicher zu gehen, dass der Code keine Speicherlöcher erzeugt, muss ich nun prüfen, ob TBar.Create, b.DoSomething und f.Work keine Exceptions werfen. Falls ich Glück habe und TBar.Create erstellt, wie ich anhand der Namen vermute, tatsächlich ein neues Objekt, bin ich allerdings schnell damit fertig, weil dann eine EOutOfMemory-Exception geworfen werden könnte und damit wäre der Code für mich definitiv gefährlich.

Geändert von HeZa (13. Aug 2011 um 11:31 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:05 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 by Thomas Breitkreuz