AGB  ·  Datenschutz  ·  Impressum  







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

Wichtigkeit von Try...Finally...End

Ein Thema von sir-archimedes · begonnen am 19. Jan 2006 · letzter Beitrag vom 20. Jan 2006
Antwort Antwort
Seite 1 von 2  1 2      
sir-archimedes

Registriert seit: 2. Jan 2006
Ort: Münster
167 Beiträge
 
Delphi 2006 Professional
 
#1

Wichtigkeit von Try...Finally...End

  Alt 19. Jan 2006, 19:20
Hallo Ihr alle,

ich wollte euch einmal mitteilen, wie dermaßen wichtig der richtige Gebrauch von try...finally-Blöcken seien kann. Bei mir im Programm sind beim Öffnen eines Dialoges plötzlich Zugriffsverletzungen aufgetreten.

Aber erstens nur auf einem System, auf dem BDS2006 nicht installiert ist - in der IDE hat sich nichts getan, daher war debuggen nicht möglich und außerdem nur manchmal. Zunächst unerklärlich. Bis ich dahinter gekommen bin, dass sie immer dann auftreten, wenn ich vorher eine bestimmte Aktion gemacht habe.

Nach stundenlanger (ich habe seit heute Nachmittag 15 Uhr danach gesucht) Suche habe ich folgendes böses Stück Code gefunden:

Delphi-Quellcode:
    ADODataSet := pLogicDataModule.GetADODataSet('SELECT ID FROM MD_InvoiceRules WHERE Active = 1 ORDER BY Mandator', true);
    try
      ProgressDialog := TJvProgressDialog.Create(NIL);
      ProgressDialog.ScreenPosition := poMainFormCenter;
      ProgressDialog.Caption := 'Rechnungserstellung';
      ProgressDialog.Text := 'Verarbeite Regeln (insgesamt '+IntToStr(ADODataSet.RecordCount)+')';
      ProgressDialog.Show;
      ProgressDialog.Position := 0;
      ProgressDialog.Min := 0;
      ProgressDialog.Max := ADODataSet.RecordCount;
      ProgressDialog.ShowCancel := False;
      while not ADODataSet.Eof do
        begin
          ProcessInvoiceRule(ADODataSet.FieldByName('ID').AsInteger, AccountingPeriod);
          ADODataSet.Next;
          ProgressDialog.Position := ProgressDialog.Position+1;
        end;
    finally
      ProgressDialog.Free;
      ADODataSet.Free;
    end;
Ich bin davon ausgegangen, dass dieser Progress-Dialog wohl keinen Schaden anrichten wird. Pustekuchen! Irgendwas hat er bewirkt. Ich denke, dass das ADODataSet nicht zerstört wurde, was dann irgendwann (immernoch unerklärlich ) zu Schutzverletzungen geführt hat.

Eine Änderung in folgendes, hat den Fehler eliminiert:
Delphi-Quellcode:
      ADODataSet := pLogicDataModule.GetADODataSet('SELECT ID FROM MD_InvoiceRules WHERE Active = 1 ORDER BY Mandator', true);
      try
        ProgressDialog := TJvProgressDialog.Create(NIL);
        try
          ProgressDialog.ScreenPosition := poMainFormCenter;
          ProgressDialog.Caption := 'Rechnungserstellung';
          ProgressDialog.Text := 'Verarbeite Regeln (insgesamt '+IntToStr(ADODataSet.RecordCount)+')';
          ProgressDialog.Show;
          ProgressDialog.Position := 0;
          ProgressDialog.Min := 0;
          ProgressDialog.Max := ADODataSet.RecordCount;
          ProgressDialog.ShowCancel := False;
          while not ADODataSet.Eof do
            begin
              ProcessInvoiceRule(ADODataSet.FieldByName('ID').AsInteger, AccountingPeriod);
              ADODataSet.Next;
              ProgressDialog.Position := ProgressDialog.Position+1;
            end;
          ProgressDialog.Hide;
        finally
          ProgressDialog.Free;
        end;
      finally
        ADODataSet.Free;
      end;
Eines habe ich daraus gelernt: Spare nicht noch einmal an Try-Finally-Blöcken.

Das wollte ich einfach mal erzählt haben

Viele Grüße,
Dominik
  Mit Zitat antworten Zitat
tommie-lie
(Gast)

n/a Beiträge
 
#2

Re: Wichtigkeit von Try...Finally...End

  Alt 19. Jan 2006, 19:31
Zitat von dominik.boehm:
Spare nicht noch einmal an Try-Finally-Blöcken.
Weiser Schluss. So viel gips da ja auch nicht zu sparen.
  Mit Zitat antworten Zitat
FlatCoder

Registriert seit: 18. Mai 2005
12 Beiträge
 
Delphi 2007 Professional
 
#3

Re: Wichtigkeit von Try...Finally...End

  Alt 19. Jan 2006, 19:40
Das was Dominik hier erwähnt ist in der Tat keine "läppische" Angelegenheit!
Das Auffangen von Fehlern mit Try..Except bzw. Try..Finally ist besonders wichtig wenn man wirklich sicher gehen will Objekte, die man erstellt hat, auch wieder freizugeben! Denn sonst läuft Speicher voll und bereits gelöscht geglaubte Daten werden von neuen Objekten in Anspruch genommen und schwupps hat man einen Fehler oder noch schlimmer: einen Absturz!

Ich kenne einige Programmierer die Objekte erstellen und dann unten irgendwann mal mit FREE wieder freigeben.
Ohne sie im TRY..EXCEPT oder TRY..FINALLY Konstrukt verpackt zu haben.
Wenn ich sie frage, warum sie das nicht machen heißt es: "Das ist nur unnötige Tipparbeit!..." oder "Warum soll da was passieren? Das läuft garantiert durch und wird später wieder freigegeben..."

Naja jeder wie ers will. Aber für mich gilt: Egal ob ein Formular dynamisch mit Application.CreateForm, oder ein Objekt erstellt wird was später wieder DESTROY't oder GEFREE't werden soll, TRY..FINALLY muss mindestens mit!

Gruß

FlatCoder
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#4

Re: Wichtigkeit von Try...Finally...End

  Alt 19. Jan 2006, 19:46
Könnte auch ein Argument sein, Factories (wie getAdoDataSet) Interface instanzen zurückgeben zu lassen. Dadurch kümmert sich der Compiler um Try-finally und man spart sich Tipperei.

btw, dein Problem verstehe ich trotzdem nicht ganz. Das Freigeben des DataSets hätte doch nur duch eine Exception im Destructor vom ProgressDialog verhindert werden können. Die wiederum hätte dir doch auffallen müssen....
Robert Giesecke
  Mit Zitat antworten Zitat
Benutzerbild von 3_of_8
3_of_8

Registriert seit: 22. Mär 2005
Ort: Dingolfing
4.129 Beiträge
 
Turbo Delphi für Win32
 
#5

Re: Wichtigkeit von Try...Finally...End

  Alt 19. Jan 2006, 19:49
Bitte mal auf Deutsch! Ich verstehe gar nix.
Manuel Eberl
„The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.“
- Terry Pratchett
  Mit Zitat antworten Zitat
tommie-lie
(Gast)

n/a Beiträge
 
#6

Re: Wichtigkeit von Try...Finally...End

  Alt 19. Jan 2006, 19:59
Zitat von Elvis:
btw, dein Problem verstehe ich trotzdem nicht ganz. Das Freigeben des DataSets hätte doch nur duch eine Exception im Destructor vom ProgressDialog verhindert werden können. Die wiederum hätte dir doch auffallen müssen....
Die einzige Konstellation, bei der ich mir vorstellen könnte, daß etwas in die Hose geht, wäre, wenn der Konstruktor von TJvProgressDialog Mist baut, eine Exception wirft *und* Mist zurückgibt. Dann steckt hinter ProgressDialog alles mögliche, nur kein gültiges Objekt. Durch die Exception springt's in den finally-Abschnitt, wo die Methode Free aufgerufen wird, aber da nix Vernünftiges bei rauskommt. Allerdings deutet das auf einen gehörigen Fehler in der RTL hin, wenn ein Konstruktor eine Exception wirft, bleibt zumindest die Instanz des Objektes gültig und ein FreeInstance() sollte nicht fehl schlagen. Aber vielleicht war es ja auch der Code des Destruktors von TJvProgressDialog, der auf unsaubere Felder zugegriffen hat.
Ich bin mir zwar nicht sicher, aber ich meine, bei try..finally wird bei einer Exception im finally-Block auch aus dem finally-Block herausgesprungen, bevor er vollständig abgearbeitet ist. Das wäre die einzige plausible Erklärung, die ich so ohne weiteres wüsste, ohne mich nochmal damit beschäftigen zu müssen, was Delphi da anstellt.


Und Exception-Handling ist performancetechnisch so billich, da kann man lieber mal eins zu viel nehmen als eins zu wenig.
  Mit Zitat antworten Zitat
Benutzerbild von Khabarakh
Khabarakh

Registriert seit: 18. Aug 2004
Ort: Brackenheim VS08 Pro
2.876 Beiträge
 
#7

Re: Wichtigkeit von Try...Finally...End

  Alt 19. Jan 2006, 20:05
Zitat von 3_of_8:
Bitte mal auf Deutsch! Ich verstehe gar nix.
http://de.wikipedia.org/wiki/Factory-Pattern
Interface ist dir hoffentlich geläufig .
Sebastian
Moderator in der EE
  Mit Zitat antworten Zitat
sir-archimedes

Registriert seit: 2. Jan 2006
Ort: Münster
167 Beiträge
 
Delphi 2006 Professional
 
#8

Re: Wichtigkeit von Try...Finally...End

  Alt 19. Jan 2006, 20:26
Zitat von Elvis:
Könnte auch ein Argument sein, Factories (wie getAdoDataSet) Interface instanzen zurückgeben zu lassen. Dadurch kümmert sich der Compiler um Try-finally und man spart sich Tipperei.
Ich gebe dir Recht - das wäre ein guter Ort, um Interfaces einzusetzen. Allerdings müsste ich dann ja nicht nur ein Interface erstellen, sondern auch noch eine von ADODataSet abgeleitete Klasse, die dann auch das Interface implementiert. Dazu müsste ich dann auf der anderen Seite auch noch eine Menge im sonstigen Quelltext ändern und das ist mir zu aufwändig. Dann lieber Old-School-Factories mit "echten Objekten"

Zitat von Elvis:
btw, dein Problem verstehe ich trotzdem nicht ganz. Das Freigeben des DataSets hätte doch nur duch eine Exception im Destructor vom ProgressDialog verhindert werden können. Die wiederum hätte dir doch auffallen müssen....
Genau das verstehe ich auch nicht. Wenn etwas schief ginge und eine Exception ausgelöst würde, dann wäre sie später aufgefallen. Habe weiter unten ein
Delphi-Quellcode:
...
  except
    // Rollback the transaction on error
    pLogicDataModule.DBConnection.RollbackTrans;
    raise;
  end;
stehen. Das sollte ja eigentlich die Exception rauslassen. Das komische ist halt, dass es in der Delphi-Umgebung alles funktioniert. Daher erhalte ich da auch keine Exception. Die kommt aber "wie erwartet" auf einem System ohne Delphi.

Einen Fehler in der RTL schließe ich eigenltich aus - der Konstruktor funktioniert einwandfrei: Mein ProgressDialog wird wie gewollt angezeigt. Evtl. geht es schief, wenn ich diesen Dialog freee, ohne ihn vorher versteckt zu haben. Aber das möchte ich nicht auch noch testen - der Fehler hat mich genug Zeit gekostet
  Mit Zitat antworten Zitat
tommie-lie
(Gast)

n/a Beiträge
 
#9

Re: Wichtigkeit von Try...Finally...End

  Alt 19. Jan 2006, 20:37
Zitat von dominik.boehm:
Mein ProgressDialog wird wie gewollt angezeigt.
Ach so?!?
Dann würde es mich ja schon mal interessieren, was denn da schief läuft. Schade, daß du keinen Nerv zu hast, das zu debuggen, aber vielleicht findest du die Neugier ja am Wochenende wieder
  Mit Zitat antworten Zitat
sir-archimedes

Registriert seit: 2. Jan 2006
Ort: Münster
167 Beiträge
 
Delphi 2006 Professional
 
#10

Re: Wichtigkeit von Try...Finally...End

  Alt 19. Jan 2006, 20:51
Zitat von tommie-lie:
Zitat von dominik.boehm:
Mein ProgressDialog wird wie gewollt angezeigt.
Ach so?!?
Dann würde es mich ja schon mal interessieren, was denn da schief läuft. Schade, daß du keinen Nerv zu hast, das zu debuggen, aber vielleicht findest du die Neugier ja am Wochenende wieder
Naja, die Neugier hat mal wieder gesiegt *g* In der TJvProgressDialog Klasse ist ein kleiner Fehler: So sieht nämlich der Destruktor aus:
Delphi-Quellcode:
destructor TJvProgressDialog.Destroy;
begin
  FreeAndNil(FImage);
  FreeAndNil(FIImage);
  inherited Destroy;
end;
Wenn der Dialog angezeigt wurde, und man ihn ohne vorheriges Verstecken zerstören möchte, dann bleibt das Fenster am Leben. Hier schafft ein "Hide" vor dem ersten FreeAndNil Abhilfe.

Allerdings erklärt das mein spezifisches Problem nicht. Mein Problem tritt ja auch nicht da - sondern ein paar hundert Zeilen später - in einem ganz anderen Modul auf. Und das ohne das ich noch einmal diesen ProgressDialog verwende. Das ganze bleibt mir ein Rätsel. Aber immerhin konnte ich so jetzt einen kleinen JVCL-Fehler verbessern Hat ja auch was!

Weiteres Debuggen werde ich nicht machen - zumal sich dieser Fehler ja auch nicht debuggen lies.
  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 14:16 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz