![]() |
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. |
AW: Schutzblöcke überflüssig!?
Zitat:
Bei meinem Code sind schutzblöcke meistens unnötig - weil ich wo immer möglich Interfacereferencen verwende. Ansonsten verwende ich die immer! Selbst wenn es technisch nicht nötig sein sollte, würde es meine Gewohnheit reduzieren, die dazu führt dass ich nicht mal einen vergesse. |
AW: Schutzblöcke überflüssig!?
Naja..so generell kann man das glaub ich nicht wirklich sagen, das Schutzblöcke überflüssig sind.
Es kommt wirklich auf die Situation drauf an. Z.b. wenn ich auf den Source der Klasse, dich ich erzeugen möchte, keinen Zugriff hab (Stichwort: Komponenten von Dritt-Anbietern), dann kann ein Schutzblock nicht wirklich schaden. Wenn ich dagegen die Klasse selbst geschrieben hab, würd ich das eher weglassen, grad während der Entwicklung. Bei Entwicklungen im Team sie es wieder ganz anders aus. Es gibt da denk ich viele Gründe für und gegen Schutzblöcke |
AW: Schutzblöcke überflüssig!?
Zitat:
Nur im HelpInsight wird dem Entwickler sowas dann angezeigt, falls er dort reinguckt. Zitat:
Zitat:
Bei uns sind nahezu alle Komponenten abgeleitet. Somit war es z.B. ein Leichtes in TTimer eine Behandlung einzufügen die nach x Fehlern den Timer disabled und eine letzte Fehlermeldung anzeigt, damit nicht millionen Fehlermeldungen aufploppen. PS: Im OnPaint Fehlermeldungen anzuzeigen ist eine super Idee. :zwinker: Fehler kommt und der wird angezeigt, Dialog ploppt auf, das Fenster bekommt spätestens beim Schließen des Dialogs mit, dass es neu gezeichnet werden muß und schon tritt der Fehler wieder auf ... Endlosschleife. Hier also nur Loggen und/oder die Komponente auf Invisible stellen (und dannach notfalls das Programm beenden, bzw. das Fenster schließen). |
AW: Schutzblöcke überflüssig!?
Der wissenschaftliche Beweis, dass man fehlerfreie Software schreiben kann, steht noch aus.
Und solange bleiben bei mir die Schutzblöcke drin. Auch wenn ich von meinem Code (in Ausnahmefällen) absolut sicher sein kann, dass da keine Fehler drinne sind und ich von daher keine Fehler erwarte, bleiben die Schutzblöcke drinne, derweil: Auch mit meiner Erwartung kann ich gehörig schief liegen. Bei jedem Objekt, dass ich erstelle, besteht die (theoretische) Möglichkeit, dass die Erstellung scheitert. Also muss das abgesichert werden. Und, egal welcher (erwartete oder unerwartete) Fehler auftritt, es spricht nichts dagegen, vorsorglich ein gesichertes Aufräumen zu implementieren. Am schlechtesten sind die Fehler zu finden, die bei der unstrukturierten Behandlung von Fehlern in der Fehlerbehandlung auftreten, die nur deshalb passieren, weil man an der fehlerverursachenden Stelle vergaß (oder es fahrlässig für überflüssig hielt) für eine geordnete Weiterverarbeitung im Programm zu sorgen. Oder ein ganz grober Vergleich: Im Auto verzichtet man auch nicht auf das Anschnallen, den Airbag, die Knautschzone, nur weil man sicher ist, dass man gut und sicher autofahren kann und keinen Unfall baut. Die Probleme kommen auch für 'nen perfekten Autofahrer häufig von außen. Und bei Software sind dieses Außen z. B. Betriebssystem, Hardware, Compiler, Bios, (Anwender sollen zuweilen auch dazu gehören ;-)), ..., die ggfls. auch (vermeintlich) fehlerfreie Software an den obskursten Stellen ins Straucheln bringen können. Und hier versuche ich durch 'ne (hoffentlich) vernünftige "Prophylaxe" möglichen Problemen aus dem Weg zu gehen. Schutzblöcke gehören da selbstverständlich zu. |
AW: Schutzblöcke überflüssig!?
Amen, Basta, ...
Zitat:
|
AW: Schutzblöcke überflüssig!?
@Delphi.Narium
Wollen wir anhand Deines Beispiels mal weiter diskutieren? Die Argumentation finde ich nämlich ganz passend. Vielleicht können wir ja irgendetwas draus ziehen... Also das Beispiel mit dem Auto passt nicht ganz zu meinem Thema. Im Falle eines Unfalles helfen Gurt und Airbag, die Folgen zu mildern. Bei der Software kann man die Analogie vielleicht bei einer Fehlerbeseitigung ziehen. Die Funktion wird abgebrochen, der Speicherbereich wird aufgeräumt, der Anwender erhält eine Nachricht und kann mit einem konsistenten Datenbestand weiter arbeiten. Soweit alles ok. Was ich nicht nachvollziehen kann, ist folgendes: Zitat:
Nehmen wir noch ein konkretes Beispiel: Wir erzeugen zwei Personenobjekte und überweisen einen Betrag.
Delphi-Quellcode:
Hier können jetzt diverse Probleme auftreten.
procedure Überweisung;
begin Person1 := TPerson.Create; Person1.LoadFromDB; Person2 := TPerson.Create; Person2.LoadFromDB; Person1.Überweise(Person2, 100); Person1.SaveToDB; Person2.SaveToDB; Person1.Free; Person2.Free; end; Wenn man die zwei Free-Anweisungen jetzt in einen Finally-Block setzt - ohne sonstige Fehlerbehandlung - findest Du weder den Fehler besser noch ist Dein Datenbestand besser geschützt noch erhält der Anwender bessere Fehlerinformationen. Nur der Speicherplatz der zwei Objekte wird wieder freigegeben. Der Aufrufer der Prozedur Überweisung weiß nichts von dem Fehler und das Programm geht davon aus, dass alles passt. Ob die Überweisung in der Datenbank realisiert wurde oder nicht, kann Dein Programm nicht nachvollziehen und der Anwender schon gar nicht. Dass der Speicherplatz der zwei Objekte freigegeben wurde hilft auch niemandem - jedenfalls sehe ich dafür keinen sachlichen Grund. Noch einmal: Eine Fehlerbehandlung und Benachrichtigung im Sinne "Überweisung ist fehlgeschlagen - bitte wiederholen! Der bisherige Datenbestand wurde nicht beeinträchtigt!" ist völlig korrekt. In dem Zusammenhang natürlich auch die Freigabe der erzeugten Objekte. Aber alle Objektfreigaben in Schutzblöcke zu kapseln, ohne eine wirkliche Fehlerbehandlung zu realisieren - das halte ich für überflüssig. Und oft wird ja so argumentiert, dass Objekte immer in Schutzblöcke gehören. Ich sehe dafür einfach keinen sachlichen Grund. @freimatz Wenn man das so gewöhnt ist und machen möchte - ok. Einen Nutzen sehe ich darin aber nicht (und habe auch noch kein überzeugendes Argument gehört). |
AW: Schutzblöcke überflüssig!?
Hoffentlich hab' ich Dich nicht falsch verstanden.
Deine Argumentation klingt im Moment für mich in etwa so (sehr grob formuliert): Wenn ich keine vernüftige Fehlerbehandlung habe, kann ich mir im Fehlerfalle auch die Freigabe von Objekten sparen. Die Prozeduren bei Dir wären bei mir schonmal Funktionen, die im Erfolgsfalle ein True zurückgeben, im Fehlerfalle ein False. Wenn die erste Funktion fehlschlägt, wird die zweite nicht mehr ausgeführt. Welchen Sinn hätte es denn, wenn eine der beiden Personen nicht aus der DB geladen werden könnte, die Überweisung durchzuführen? Und dann das Ergebnis auch noch speichern? Meiner Meinung nach ist Dein Beispiel schon logisch grob falsch, von daher halte ich anhand eines derartigen Beispiels eine Diskussion über die Sinnhaftigkeit von Schutzblöcken für nicht angebracht. Oder mal wieder sehr dreist formuliert: Wer so schlecht programmiert, kann sich auch Schutzblöcke sparen, die machen den Kohl dann auch nicht mehr fett. Zitat:
PS: Das Autothema passt sehr gut. Du argumentierst Zitat:
Zitat:
Durch die Einführung dessen, dessen Nutzen Du bezweifelts, widerlegst Du ein Beispiel für den Sinn dessen, was Du bezweifelts? Ehrlich gesagt: Auf so eine Diskussion hab' ich keine Lust. |
AW: Schutzblöcke überflüssig!?
Zitat:
Wenn man (in möglichen Fehlerfällen) Rückgabewerte nutzt und den Programmablauf entsprechend steuert, ist das völlig in Ordnung (das Beispiel hatte ich ich auch gebracht). Das ist auch nicht der Ansatz, den ich kritisiert habe. Ohne Fehlerbehandlung ist die Freigabe von Objekten im Fehlerfall nebensächlich - genau das UND NUR DAS meine ich. |
AW: Schutzblöcke überflüssig!?
Zitat:
Zitat:
|
AW: Schutzblöcke überflüssig!?
Zitat:
In Deutschland kommt demnächst vermutlich ein neuer französischer Kleinstwagen auf den Markt und dort wird kein Airbag eingebaut und für Knautschzone ist sowieso kein Platz ... du mußt dir nur eine passende Begründungen ausdenken, dann passt es schon. :zwinker: * der ist so langsam, da passiert schon nichts * und falls dir ein SUV oder LKW reinrauscht, dann ist eh alles egal Das Ding ist unter Anderem auch für Jugendliche ab 16/17 Jahren gedacht (Motoradführerschein A1) und die fahren bekanntlich sooo sicher und routiniert, dass da keine Unfälle zu erwarten sind. Bezüglich Fehlerbehandlung oder Rückgaben auswerten ![]() |
AW: Schutzblöcke überflüssig!?
Der verlinkte Thread zeigt ja, dass es diverse Ursachen für
Zitat:
Man kann selbst noch so gut, gewissenhaft, sicher und (hoffentlich) fehlerfrei programmieren. Man weiß nun mal nicht, ob die genutzten Bibliotheken, Compiler, ... absolut fehlerfrei sind, ob alle genutzen Betriebssystemfunktionen fehlerfrei sind, ... Also wird versucht das "eigene Zeugs" so zu schreiben, dass man bei allen Fehlern, bei denen man erahnt, dass sie passieren könnten, eine sichere Fehlerbehandlung, eine sichere Freigabe von Resourcen, ... implementiert. Und ja: Die Implemetierung all dessen ist aufwändig, wenn man Pech hat macht's sogar den größten Teil der Programmierung aus. |
AW: Schutzblöcke überflüssig!?
Zitat:
Und nun nehmen wir mal an der Code wird in einem Programm immer wieder aufgerufen, das länger läuft, z.B. ein Webservice... da ist dann irgendwann trotz sauberer Behandlung der Exceptions der Speicher voll. Wenn es nur um wenige Aufrufe geht, merkt man in der Tat nicht viel davon. Aber das Programm benutzt eben mehr Speicher als nötig. Noch schlechter wird es, wenn man in dem Objekt ein Handle auf eine Datei offen hat oder ähnliches, so dass die Datei dann gesperrt bleibt bis das Programm beendet wird. Und damit man das nicht immer neu bewerten muss, macht es Sinn einfach immer eine korrekte Behandlung solcher potentiellen Probleme einzubauen. Denn sonst müsstest du ja bei jeder Änderung schauen, ob deine Prozedur nicht irgendwo aufgerufen wird, wo dann eine Behandlung nötig wird... Davon abgesehen bringt ein Ressourcenschutzblock nur etwas, wenn er auch korrekt aufgebaut ist (Konstruktoraufruf vor dem try, sonst springt man bei einer Exception im Konstruktor auch in das finally obwohl die Variable noch gar nicht zugewiesen ist und dann knallt es ggf. dort erneut):
Delphi-Quellcode:
procedure Run;
begin obj1 := TObject.Create; try Beep; obj2 := TObject.Create; try obj3 := TObject.Create; try Beep; finally obj3.Free; end; finally obj2.Free; end; finally obj1.Free; end; end; try Run; except on E: Exception do begin WriteLog(E); UserDialog(Format('Interner Fehler: %s - %s', [E.ClassName, E.Message])); end; end; |
AW: Schutzblöcke überflüssig!?
Zitat:
"ist doch nicht so schlimm, wenn es nochmal knallt ... der Nutzer bekommt ja dennoch nur einen Fehler zu sehen" aber das stimmt nicht, denn er und ein eventuelles Logging bekommt nur den letzten Fehler zu sehen und die "eigentliche" Fehlermeldung und Position ist dann weg, was echt blöd für die Fehlersuche ist. Das ist genauso schlimm, wie wenn man im Except den Fehler abfängt und den Fehlertext durch einen sinnlosen und nichtssagenden Text ersetzt. Und da die Vairale nicht initialisiert ist, kann sie sonstwo hinzeigen, wodurch dann das Free nochmal richtig was im Speicher zerstören kann, und somit die Funktion seines Programm dann richtig schädigen würde. |
AW: Schutzblöcke überflüssig!?
Ja, danke Sebastian.
Deinen Text kann ich nachvollziehen und da gehe ich auch weitestgehend mit. Dein Beispiel ist grundsätzlich auch in Ordnung, da Du eine Exception auswertest und darauf reagierst. Oft sieht man aber Beispiele wie Dein "Run" alleinstehend, wo die Objekte wieder freigegeben werden und keine Fehlerbehandlung ersichtlich ist. Das finde ich dann halt unsinnig. Folgenden Punkt Deiner Ausführungen sehe ich aber dann doch anders: Zitat:
Entweder weiß ich von vorn herein, dass an bestimmten Stellen ein Exception-Problem auftreten kann, das berücksichtigt werden muss oder ich merke es bei der Entwicklung bzw. in einer Testphase. Wenn ich 1000 Stellen im Code mit Schutzblöcken absichere und nur eine ein wirkliches Risiko beinhaltet, dann finde ich den Aufwand einfach nicht zu rechtfertigen (zumal der Code auch schlechter wartbar wird). Wenn das mögliche Problem in Deinem Beispiel nicht vermeidbar ist (z.B. Netzkabel gezogen) und Deine Exceptionbehandlung das Problem vollständig löst, so dass das Programm korrekt mit konsistenten Daten weiter arbeitet, dann ist die Lösung absolut sinnvoll. Eine Datenbereinigung ist dort jedoch auch nicht skizziert, sondern nur ein Log und eine Infobox. Wenn KEINE ausdrückliche Datenbereinigung erfolgt, dann muss vor einer Fortsetzung der Arbeit erst mal der Datenbestand gesichert/geprüft und der Fehler in der Software schnell bereinigt werden. In dem Moment komme ich wieder zu dem Schluss, dass die finallys in dem Run völlig verzichtbar sind: Dein Code wäre dann m.E. gleichwertig zu folgendem:
Delphi-Quellcode:
Hier mal angenommen, der Fehler wäre nicht komplett ausgebügelt und der Datenbestand möglicherweise inkonsistent.
procedure Run;
begin obj1 := TObject.Create; Beep; obj2 := TObject.Create; obj3 := TObject.Create; Beep; obj3.Free; obj2.Free; obj1.Free; end; try Run; except on E: Exception do begin // VollständigeDatenprüfungUndBereinigung; WriteLog(E); UserDialog(Format('Interner Fehler: %s - %s', [E.ClassName, E.Message])); end; end; In beiden Fällen erhalten wir eine Info und einen Log aber wir wüssten nicht, was nun mit den Daten ist. Der Fehler müsste bereinigt werden und das Programm ein Update erhalten. Eine Weiterarbeit wäre dem Anwender nicht zu empfehlen, weil wir nichts über den Datenbestand sagen können. Die verkürzte Run-Prozedur hätte keine wirklichen Nachteile gegenüber Deiner. Ok, da dümpeln noch 1 - 3 Speicherbereiche im Speicher rum, aber das Programm muss ja sowiso beendet werden. Wenn da natürlich die VollständigeDatenprüfungUndBereinigung eingebaut wäre, dann wäre Deine Lösung perfekt und absolut richtig. Fazit: - Exceptionbehandlung mit Datenbereinigung -> Object.Free im Finally sinnvoll - keine Exceptionbehandlung mit vollständiger Datenbereinigung -> Object.Free im Finally nicht hilfreich Und vollständige Datenbereinigung bei möglichen Fehlern kann man nur bei erwarteten bzw. denkbaren Fehlern durchführen. |
AW: Schutzblöcke überflüssig!?
Zitat:
Zitat:
Ein Block ist in 5 Sekunden gemacht. Die Fehler oder Memory-Leak suchen, weil irgendein so ein :roll::wall: mal gemeint hat auf einem Block verzichten zu können oder es vergessen hat, dauert teilweise Tage. |
AW: Schutzblöcke überflüssig!?
Zitat:
Aber das die irgendwann mal ein Speicherleck gefunden haben, hab' ich nie erlebt. |
AW: Schutzblöcke überflüssig!?
Zitat:
Wenn man z.B. mit Netzwerkverbindungen arbeitet muss man immer mit Abbrüchen rechnen und darauf reagieren. An anderen Stellen wird aber doch mit getesteten Klassen und Bedingungen gearbeitet, wo keine Exceptions zu erwarten sind. Wenn irgendwann doch Probleme erkannt werden, muss man eben doch nachbessern. Das gehört für mich zu ordentlichen Tests. Zitat:
Wenn es ordentlich gerumst hat wirst Du bestimmt nicht schauen, ob der Speicher zuvor korrekt aufgeräumt wurde. Du musst den Fehler finden und das Programm sowie die Daten bereinigen. Wenn das Programm korrekt läuft, werden alle Free ausgeführt und es gibt kein Speicherleck. Nur wenn es unerwartet Knallt, würde ein solches entstehen - aber dann hat man sowieso deutlich größere Probleme. Mit einer Problemlösung ist auch das Speicherleck automatisch wieder vom Tisch. Ich verstehe nicht, dass Du (weitestgehenden) Verzicht auf Schutzblöcke mit Gleichgültigkeit gegenüber Speicherlecks gleichsetzt. Das hat doch gar nichts miteinander zu tun. |
AW: Schutzblöcke überflüssig!?
Zitat:
Die Schutzblöcke sind für die unerwarteten Fehler. Wenn ich mit Netzverbindungen arbeite, dann wird dort, wo die Netzverbindung genutzt wird, eine Fehlerbehandlung implementiert, so dass von dort keine Exception "irgendwo ins Programm fliegen kann" und erst recht kein Programmzustand erreicht werden kann, bei dem eigentlich nur noch "ein Abschuß des Programmes" sinnvoll erscheint. Zitat:
Zitat:
Und ein Programm nach den Kriterien zu entwickeln, dass es im Extremfall egal ist, wenn was nicht freigegeben wird, ist mir zu kompliziert. Meine Routinen sollen sowohl im Normalfall, als auch im Ausnahmefall, möglichst sauber arbeiten. Aber irgendwie sind unsere Ansichten zu dem Thema sehr unterschiedlich. Also lassen wir es dabei. |
AW: Schutzblöcke überflüssig!?
Zwei Antworten möchte ich nochmal los werden (zum vielleicht besseren Verständnis):
Zitat:
Das muss sicher gestellt sein aber mehr ist nicht notwendig. Notfalls ist eine schnelle Nachbesserung erforderlich. Zitat:
Bei einem unerwarteten Fehler arbeitet Dein Programm ohnehin nicht mehr sauber - das geht grundsätzlich nicht. Wenn es sich dagegen um ein erwartetes Problem handelt, das im Rahmen einer Exception behandelt und gelöst werden kann, dann ist es etwas völlig anderes - darum ging es mir aber nicht. Insofern hat sich meine Einschätzung nicht geändert. Aber danke für alle sachlichen Beiträge, auch wenn ich da mit der gängigen Einschätzung offenbar nicht überein stimme. PS: Ich denke übrigens, dass ich ganz ordentlich und sauber programmiere (auch wenn ich kein Profi bin). Meine Programme laufen schon ganz zuverlässig und ohne Exceptions sowie die aktuelleren auch ohne Speicherlecks. :-) |
AW: Schutzblöcke überflüssig!?
Zitat:
tryf[enter] oder trye[enter] oder über das Refactoring "umgeben" An extremeinfachen oder zeitkritischen Stellen z.B. "geziehlt" keine Fehlerbehandlung zu machen würde ich als "Ausnahme" ansehen. Das überdenkt man und schaut genauer hin und es wird an der Stelle dann auch dokumentiert, damit sich niemand wundet, weil dort was zu fehlen scheint. |
AW: Schutzblöcke überflüssig!?
Ich frage mich vor allem wo die Motivation eigentlich liegt. Leider sehe ich es viel zu oft, dass auf Kosten der Lesbarkeit (zu kurze Variablennamen) oder Wartbarkeit (with) ein paar geschriebene Zeilen oder Zeichen im Quelltext gespart werden (oder eben um ein paar Mikrosekunden an unwichtigen Stellen zu sparen wie bei try..finally weglassen). Zeichen im Quelltext zu sparen ist aber so ziemlich der unwichtigste Punkt, den es überhaupt gibt und die Performance im Bereich von try..finally ist auch meistens egal...
Viel wichtiger ist doch, dass der Code robust ist (eben nicht z.B. nach Änderungen plötzlich Speicherlecks verursachen kann), wartbar, lesbar ist usw., wofür es eben Konventionen zur Codeformatierung und aber auch zum Schreiben von Code in der jeweiligen Sprache gibt. Und dazu gehören in Delphi auch die Ressourcenschutzblöcke. |
AW: Schutzblöcke überflüssig!?
Zitat:
Das passiert nur EINMAL, nach 12 Jahren Betrieb ... Wegen sowas stürzen Flugzeuge ab :stupid: |
AW: Schutzblöcke überflüssig!?
Zitat:
Zitat:
Zitat:
Wie gesagt, das Programm läuft normalerweise stabil und alle Objekte werden immer freigegeben. Nach 1 Jahr tritt ein unerkannter Fehlerfall auf, der Kunde ruft an und beschwert sich über eine Fehlermeldung und fragt, ob seine Daten noch stimmen. Dann muss das Problem geklärt werden. Ob Person.Free noch durchlaufen wurde oder nicht, interessiert da nicht wirklich - nur welche Daten noch geändert und gespeichert wurden und wie sichergestellt werden kann, dass der Fehler nicht wieder auftritt. Aber wir kommen da halt nicht zusammen. Lassen wir es dabei. Es sehe es ja nicht als schädlich an, so zu arbeiten, nur halt als unnötig. |
AW: Schutzblöcke überflüssig!?
Zitat:
Stelle dir vor, diese procedure läuft in einen Webserver bei einem Zahlungsdienstleister wie PayPal. PayPal hat Millionen Kunden weltweit. Jetzt nutzen 5000 Leute pro Stunde die Überweisungsfunktion. Aus irgendeinen Grund schlägt LoadFromDB() oder Überweise() oder SaveToDB() fehl. Der eigentliche Grund ist unerheblich. Man kann es sich vorstellen, also wird es passieren. Im schlimmsten Fall hast du dann 10000 TPerson-Instanzen pro Stunde, die dir den Speicher deines Webservers zumüllen. Selbst unter 64-Bit ist dann durch Speicherfragmentierung irgendwann Schluss. Ohne unhöflich sein zu wollen, aber da trennt sich wirklich die Spreu vom Weizen bzw. der Hobby-Programmierer vom Professional, der einfach schon zuviel (Schlimmes) gesehen hat und aus bitterer Erfahrung gelernt hat. |
AW: Schutzblöcke überflüssig!?
Ok, das ist ein gutes Beispiel und das kann ich auch nachvollziehen.
ABER: Dann muss allerdings auch eine Problembehandlung erfolgen und neben dem Freigeben der Objekte eine Fehlerbehandlung und Info an den Aufrufer erfolgen. Dann passt das ja wieder. Wenn aber nur die Objekte abgeräumt werden und der Aufrufer keinerlei Info erhält, dass etwas schief gelaufen ist, dann hat Paypal schnell ein echtes Problem. Vielleicht habe ich die Beispiele, die man immer wieder sieht, wo also nur ein finally-Block ohne exception-Behandlung gezeigt wird, zu wörtlich genommen. Wenn damit immer auch eine Fehlerbehandlung verbunden wird, dann ist ja alles gut. (Notfalls kann ich mal anhand eines kleines Demos und Videos den genaue Hintergrund meiner Frage noch besser verdeutlichen, wenn das jemand möchte.) |
AW: Schutzblöcke überflüssig!?
Zitat:
Oder ganz anders: Durch einen Buffer Overflow wird Speicher überschrieben und deshalb knallt es an einer ganz banalen Stelle, an der du ansonsten nie eine Exception vermuten würdest. So etwas lässt sich dann leider auch nicht immer so schnell lösen, vor allem wenn es sich nicht um eine einfach vorhersagbare Speicherstelle handelt (auf die man dann einen Datenhaltepunkt setzen kann). Was ist dann besser? Ein Programm, bei dem Exceptions soweit möglich behandelt sind und durch Ressourcenschutzblöcke keine Speicherlecks auftreten, so dass es bis zu einer Lösung weitgehend normal weiter läuft, oder ein Programm, das man dann quasi gleich stilllegen kann bis eine Lösung gefunden ist, weil aufgrund des Fehlers der Speicher voll läuft? Deine Vorstellung bezüglich des Ausschließens von Fehlern hört sich irgendwie so an als würdest du ausschließlich von relativ überschaubaren Programmen reden, an denen nur eine Person arbeitet. Bei größeren Programmen funktioniert diese ideale Vorstellung aber nun einmal nicht. Außer es handelt sich im so etwas wie einen Autopiloten, bei dem aber auch sehr viel mehr Ressourcen in die Qualitätssicherung gesteckt werden als bei normalen Programmen (hoffentlich :lol:). Oder anders: Was wäre denn, wenn man bei dem Autopiloten deiner Logik folgen würde und sich darauf verlässt, dass keine unvorhersehbaren Fehler auftreten? Was, wenn dann doch ein Fehler passiert (siehe Tesla)? Soll man dann immer noch einfach sagen: Zitat:
Unsere Anwendungen arbeiten auch nach unerwarteten Fehlern ggf. normal weiter. Es kommt nur darauf an wo ein Fehler auftritt. Das heißt nicht, dass solche Fehler dann nicht behoben werden müssen, aber man hat nicht direkt das Problem, dass vor Ort gar nichts mehr läuft. |
AW: Schutzblöcke überflüssig!?
Zitat:
Und eine Beschwerde / Frage, ob de Daten noch sicher und in Ordnung sind, mag es ja geben, aber die Antwort muss immer sein: Ja die Daten sind sicher, die Daten sind in Ordnung. Wenn man da als Entwickler nicht sicher ist, dass man immer diese Antwort geben kann, hat man was falsch gemacht. Ein Programm muss immer so geschrieben sein, dass auch bei einem schweren und unerwarteten Fehler, die Sicherheit der Daten garantiert ist. Auch dann noch, wenn der Anwender das Programm gegen alle Regeln der Vernunft weiter benutzt, neu startet und die zum Fehler führende Aktion wieder ausführt, das schlimmstenfalls mehrfach ... Der größte Aufwand beim Programmieren ist nicht, richtigen und sauber funktionierenden Code zu schreiben und für eine korrekte Arbeit des Programmes zu sorgen, sondern sicherzustellen, dass bei allem davon abweichenden die Sicherheit und Korrektheit weiterhin garantiert ist. Sprich: Die Fehlerbehandlung macht deutlich mehr Arbeit, als die eigentliche Progammlogik. Und Schutzblöcke sind ein kleiner Teilbereich dessen. @jaenicke Jo, det isset. Egal was in einem Programm an Fehlern passiert: Es läuft weiter und zwar ohne jegliche Einschränkung. Einen Fehler, der zu dem von stahli angesprochenen Szenario führt, dass es egal ist, ob man aufräumt oder nicht, darf es in Software für den professionellen Einsatz nicht geben Punkt. Und mindestens ein Dutzend Ausrufezeichen. |
AW: Schutzblöcke überflüssig!?
@jaenicke
Ja, meine Anwendungen sind recht überschaubar und ich arbeite allein daran. Zitat:
Da es sich aber um völlig unerwartete Fehler handelt, für die man keine Behandlung vorgesehen hat, ist schwer zu sagen, was aktuell besser ist. Mir ging es halt wirklich nur um solche Beispiele wie im Eingangspost, die man immer wieder überall findet. Der Speicher läuft ja nicht gleich voll, wenn der Fehler einmal pro Monat aufläuft und das Programm ansonsten zuverlässig ohne Datenverlust funktioniert. Dann kann man "in Ruhe" den Fehler bereinigen. Wenn das Problem dagegen jede jede Minute auftritt (auch ohne Datenverlust) und nicht gleich gelöst werden kann und sonst den Speicher vollmüllt, dann kann man die Freigabe vielleicht in einen finally-Block setzten und die Fehlermeldung zunächst unterdrücken - bis man den Fehler vernünftig klären kann. Aber das wäre natürlich nur ein notfalls akzeptabler Workaround. Solch einen ständig auftretenden Fehler würde man doch aber normalerweise schon in Tests finden und vermeiden, denke ich. Ok, vielleicht sehe ich das zu optimistisch durch meine recht überschaubaren Projekte. @Delphi.Narium Dann können wir vielleicht zu dem Schluß kommen, dass das eingangs von mir besprochene Beispiel (das man immer wieder findet) tatsächlich nicht viel Wert hat, da dort keine Fehlerbehandlung erfolgt. Mit Fehlerbehandlung ist das ja dagegen alles in Ordnung. |
AW: Schutzblöcke überflüssig!?
Zitat:
|
AW: Schutzblöcke überflüssig!?
Zitat:
Und man sollte sie als abschreckende Beispiele betrachten. Sie sind für den professionellen Einsatz sinnlos, kontraproduktiv, absolut ungeeignet. Wenn ich mal was für mich programmiere oder nur 'ne schnelle Routine für 'ne einmalige Aufgabe, die nur ich nutze, spar' ich mir die Schutzblöcke auch. Aber das sind Routinen, die ich nur einmalig brauche, um was grundsätzlich auszuprobieren, einmalig 'ne Datei von Zustand A in den Zustand B zu bringen, ... Aber wenn die Software von jemand anderem genutzt werden soll und das nicht nur einmalig, sondern dauerhaft im Geschäftsbetrieb, oder als dauerhaft nutzbares Hobbyprogramm, dann versuche ich das Programm so zu schreiben, dass es immer korrekt und sauber läuft, alles freigibt, immer verwertbare Fehlermeldungen ausgibt, und das auch noch in den Situationen, mit denen ich im Lebtag nicht gerechnet hätte, dass sie überhaupt möglich sein könnten. Selbst bei der Nutzung der Software vom größtmöglich denkbaren DAU, muss die Software noch sauber laufen. Und auch wenn im laufenden Betrieb Teile der Hardware abrauchen (Festplatte kaputt), verlustig gehen (Netzkabel gezogen, USB-Datenträger einfach mal eben so abgezogen), ..., muss bei professioneller Software die Datensicherheit garantiert werden können. (Hierunter fallen natürlich keine Datenverluste durch Hardwareschäden, aber die Daten auf 'nem vom Anwender einfach mal so abgezogenen USB-Datenträger, sollten konsistent bleiben.) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:17 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