![]() |
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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:45 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