![]() |
Schutzblöcke überflüssig!?
Mal eine ketzerische Behauptung...
Ich möchte das ganz gern mal diskutieren, weil ich immer wieder auf Schutzblöcke stoße, die ich für unnötig halte... Vermutlich stehe ich da wieder ziemlich allein, aber der Sinn von generellen Schutzblöcken um alle erzeugten Objekte erschließt sich mir einfach nicht... Ich halte Schutzblöcke im Allgemeinen für völlig überflüssig, außer dort, wo bestimmte Fehler ausdrücklich erwartbar sind: Folgender Code wird niemals einen Fehler produzieren:
Delphi-Quellcode:
Wenn doch, liegt das an irgendeinem Hardwareproblem oder Compilerfehler, der von der eigenen Software nicht beeinflussbar ist.
obj1 := nil;
obj2 := nil; obj3 := nil; Beep; obj1 := TObject.Create; obj2 := TObject.Create; obj3 := TObject.Create; Beep; obj1.Free; obj2.Free; obj3.Free; Insofern ist es völlig unsinnig, die Objektfreigaben in einen finally-Abschnitt zu packen. Der Code wird viel länger und unübersichtlicher und es gibt überhaupt keinen wirklichen Nutzen. Bei mehreren verschachtelten Schutzblöcken wird es immer unübersichtlicher.
Delphi-Quellcode:
Die Ausstattung des Codes mit Schutzblöcken erzeugt also mehr Aufwand und verringert die Übersichtlichkeit.
obj1 := nil;
obj2 := nil; obj3 := nil; try Beep; obj1 := TObject.Create; obj2 := TObject.Create; obj3 := TObject.Create; try Beep; except // Exception handling end; finally obj1.Free; obj2.Free; obj3.Free; end; Während der gesamten Laufzeit der Anwendung wird das Programm mit 99,99999%iger Sicherheit an diesen Stellen niemals eine Exception werfen. Die Schutzblöcke sind hier also völlig überflüssig. Natürlich gibt es auch Fälle, wo Schutzblöcke etwas nachvollziehbarer sind. Wenn wir jetzt in dem Code statt Beep eine Funktion DivHundretBy(X: Integer)aufrufen und dort verschiedene Werte DivHundretBy(Random(10)) übergeben, erhalten wir irgendwann bei den Tests den Laufzeitfehler "Division durch Null". Während der Programmentwicklung ist es erst mal egal, dass die zuvor erzeugten Objekte beim Stopp der Anwendung nicht freigegeben wurden. Das ist absolut unerheblich. Wir werden den Fehler nun bereinigen. Je nach Bedarf wird ausgeschlossen, dass die Funktion mit 0 ausgerufen wird DivHundretBy(Random(9)+1) oder es gibt eine andere Behandlung dieses Sonderfalles. Danach können wir wieder sehr sicher sein, dass die Berechnung fehlerfrei (ohne werfen einer Exception) funktionieren wird und der Finally-Abschnitt ist wieder verzichtbar. Wir werden so oder so niemals eine Exception erhalten und die Objekte werden immer korrekt freigegeben und die berechneten Werte stimmen (Programm arbeitet fehlerfrei). Wenn man während der Projektentwicklung solch eine Problemstelle übersehen hat und der Endanwender eine Exception-Meldung erhält, muss der Fehler natürlich schnellstmöglich bereinigt werden. Ob die 3 o.g. Objekte in dem Moment freigegeben werden oder nicht, ist nebensächlich. Das wäre nur interessant, wenn im Sekundentakt tausende neue Speicherlecks entstehen und aufgeräumt werden müssten. Im Grunde kann der Anwender mit dem Programm so oder so erst mal nicht mehr sinnvoll arbeiten, weil man erst mal nicht einschätzen kann, ob der Datenbestand überhaupt noch konsistent ist oder nicht. Hier steht halt dringend eine Fehlerbereinigung aus, aber ob die 3 Objekte nun noch freigegeben wurden oder nicht, spielt keine wirkliche Rolle. Jedenfalls sehe ich den Aufwand, den Code dagegen mit try...finally um alle Objekterzeugungen und Freigaben zuzupflastern als völlig unverhältnismäßig an. Da ist mir schlanker, funktionierender Code deutlich lieber. Die Fehlerbereinigung muss identisch durchgeführt werden. Natürlich gibt es auch Fälle, wo immer mit einem Problem gerechnet werden muss, dass man selbst nicht beeinflussen kann. Als Beispiel gäbe es da Erzeugen von Ordnern, Netzwerkunterbrechungen, Zugriffsfehler auf Dateien o.ä. In den Fällen macht es natürlich schon Sinn, mit Schutzblöcken zu arbeiten und z.B. Speicherbereiche direkt wieder frei zu geben. Das sehe ich dann aber als "geplanten Ablauf der Anwendung" an. Es gehört halt zu Anwendung dazu, dass z.B. ein Ordner nicht erstellt werden kann oder eine Verbindung unterbrochen wird. Wenn man das Problem nicht zuvor selbst auschließen kann (wie z.B. bei einer Division durch Null), dann kann man zumindest auf den Problemfall gezielt reagieren und einen Programmablauf vorsehen. Aber Schutzblöcke generell um Objekterzeugungen halte ich in den allermeisten Fällen für unnötig. |
AW: Schutzblöcke überflüssig!?
Einfach nur Nein!
|
AW: Schutzblöcke überflüssig!?
Würde ich auch sagen.
Wo soll man anfangen? Es gäbe so vieles, das man erwidern könnte... Mobile Anwendungen - wenn auch nur eine Exception nach draußen zum Betriebssystem gelangt, ist das der Moment, in dem die App kommentarlos beendet wird. Als Entwickler mag man Werkzeuge haben, um die Logfiles einzusehen - der normale Anwender steht auf dem Schlauch. Innerhalb eines Except- oder Finally-Blocks hast Du (je nach Situation) durchaus die Chance, die Anwendung wieder in einen kontrollierten und kontrollierbaren Zustand zu bringen und so zu retten. Deiner Aussage, dass eine Anwendung im Falle einer Exception grundsätzlich verloren ist, mag ich so pauschal nicht zustimmen. |
AW: Schutzblöcke überflüssig!?
Ich programmiere seit Turbo-Pascal 3.0 (und vorher mit Basic). Also ca. 40 Jahre.
Damals gab es keine Schutzblöcke und man musste einfach an alle möglichen Fehlerfälle denken. So programmiere ich auch heute noch. Dennoch ergeben Schutzblöcke Sinn. Es ist auch für den Anwender besser, wenn dieser eine sinnvolle Fehlermeldung bekommt und das Programm trotz einer Exception nicht abstürzt. Die Speicherlecks sind da meistens noch relativ unwichtig. Der Anwender wird froh sein, dass trotz eines Programmfehlers seine Bearbeitung mit dem Programm nicht verloren geht. Ohne Schutzblöcke sähe das völlig anders aus. Ich denke, dass man es in beide Richtungen übertreiben kann. |
AW: Schutzblöcke überflüssig!?
Hallo,
Zitat:
Dann Wenn das Objekt nicht erzeugt wird, sondern nur Methode2 aufgerufen wird, schmiert der Code beim Beep ab. |
AW: Schutzblöcke überflüssig!?
Zitat:
Zitat:
oder alles ist zu spät, dann isses sowieso egal. (Speichermanagement oder Stack zerballert) Wenn mehr als TObject und es im Create knallen kann, dann fehlt die Freigabe der vorherrigen Objekte. Mehrere Free in ein Finally nur, wenn es "normalerweise" nicht im Free/Destroy knallen kann. (Fälle wo die Anwendung eh nicht mehr lauffähig ist, ignoriere ich ... z.B. Speichermanagement/Stack total kaputt) Aber ja, teilweise optimiere ich auch das Eine oder Andere Try-Finally weg und verwende ein gemeinsames Finally oder die Zeile nach einem Try-Except (ohne Re-Raise), bzw. wenn "nachweißlich" im Create/Destroy nichts passieren kann, gleich alles weg. Zitat:
OK, wobei die VCL/FMX und (schlimmernoch) TThread viele Exceptions vom System fern halten. |
AW: Schutzblöcke überflüssig!?
Zitat:
Das vermisse ich an Java am meisten... |
AW: Schutzblöcke überflüssig!?
Zitat:
Aber nur
Delphi-Quellcode:
Halte ich für unnütz. Da wird keine Fehlernachricht ausgegeben und keine Fehlerbehandlung durchgeführt (außer die Speicherfreigabe).
try
ObjektErzeugen; EtwasTun; finally ObjektFreigeben; end; Allerdings weiß ich nicht, wie sensibel mobile Apps gehändelt werden müssen. Ich hatte nur Windowsanwendungen im Blick. Zitat:
Wenn das oder das zutrifft ... das sind m.E. Kriterien, mit den die Anwendung umgehen können muss. Wenn später Sonderfälle entdeckt werden, die noch unbehandelt sind, muss das natürlich nachgebessert werden. Aber ob die drei Objekte sofort mit dem Werfern der Exception aufgelöst werden oder nicht, macht doch keinen Unterschied. Deine Anwendung läuft nach der Fehlermitteilung weiter und greift weiter auf die Speicherstellen zu, die noch die richtigen oder falsche Daten enthalten. Entweder läuft das Programm mit richtigen oder falschen Daten weiter oder es gibt weitere Exceptions. Ich sehe da keinen Vorteil, dass die Speicher der drei Objekte zuvor freigegeben wurden. Zitat:
Dein letzter Satz passt nicht. Vermisst Du sowas in Delphi? Soweit würde ich übrigens nicht gehen wollen. Wenn die Anwendung sicher stellt, dass z.B. ein Order "A" oder Ordner "B" erzeugt werden kann, dann muss man m.E. dafür keine Exceptionbehandlung erzwingen. Der Programmierer sollte aber aus eignem Interesse hier eine einrichten, wenn ein entsprechendes Problem vermutlich mal auftreten kann. |
AW: Schutzblöcke überflüssig!?
Delphi-Quellcode:
Die Frage ist doch eher, wie wichtig ist die Sicherheit in deiner App ?
procedure LebenswichtigeFunktion_SelfDriveCar_Ausweichmanöver;
begin try ObjektErzeugen; EtwasTun; finally ObjektFreigeben; end; end; ... ... ... procedure MainLoop; begin while True begin if ObjektVoraus then begin LebenswichtigeFunktion_SelfDriveCar_Ausweichmanöver; end; end; end; <== Wenn es crasht (z.B. out-of-memory) ohne try-finally fliegt es raus, OHNE Kontrolle <== Mit try-finally hat man die Chance das es beim 2ten Mal noch funktiniert |
AW: Schutzblöcke überflüssig!?
Zitat:
Das wäre so ein oben beschriebener Fall, dass im Sekundentakt neue Probleme auftauchen. Das könnte man als Sonderfall ansehen - wobei dann neben der Speicherfreigabe auch wieder eine echte Fehlerkorrektur erfolgen müsste, damit das Sinn macht. Wie gesagt, es ging mir um reine Objektfreigabe im Finallyblock ohne Loop und ohne wirkliche Fehlerbehandlung. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:59 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