Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Verständnisfrage zu try-except-finally (https://www.delphipraxis.net/133304-verstaendnisfrage-zu-try-except-finally.html)

BAMatze 29. Apr 2009 13:22


Verständnisfrage zu try-except-finally
 
Hallo an alle DPler,

Hab eine Frage zu try-except-finally. Also ich habe schon sehr erfolgreich try-except-Abfragen in meinem Projekt eingebaut und alles lief wunderbar. Hier mal ein kleines Beispiel:

Delphi-Quellcode:
function TControlerBoard.anaAusgang_einschalten: boolean;
begin
  try
    if sKameraposition = 'oben' then
      begin
        OutputAnalogChannel(1,Diodenhelligkeit[1]);
        anaAusgang_ausschalten(2);
      end
    else
      begin
        OutputAnalogChannel(2,Diodenhelligkeit[2]);
        anaAusgang_ausschalten(1);
      end;
    result := true
  except
    // Fehlermeldung
    result := false;
  end;
end;

function TControlerBoard.anaAusgang_ausschalten(iNummer: Integer): boolean;
begin
  try
    ClearAnalogChannel(iNummer);
    result := true
  except
    // Fehlermeldung
    result := false;
  end;
end;

function TControlerBoard.alle_anaAusgeange_ausschalten;
begin
  try
    ClearAllAnalog;
    result := true
  except
    // Fehlermeldung
    result := false;
  end;
end;
Sind ein paar Funktionen für ein Controler-Board und wie gesagt, bin sehr zufrieden damit. Jetzt versuche ich in meiner Komponente ebenfalls eine try-except-Abfrage zu machen und bekomme trotz das ich den eigentlichen Fehlerpunkt damit "umschließe" immer eine Fehlermeldung und ich weiß einfach nicht, warum dies der Fall ist.

Hier meine derzeitige Routine an der ich arbeite.
Delphi-Quellcode:
procedure TContainer.Beschleunigungmanuellverlassen(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var Index: integer;
    dWert: double;
begin
  if Key = 13 then
    begin
      try
        dWert := strtofloat(FEdmanuelleBeschleunigungsEingabe.Text) // <-- Hier tritt der Fehler auf
      except
        Showmessage('Hier');
      end;
    end;
end;
Hab die Stelle markiert, wo der Fehler auftreten kann. Eigentlich, so aus meinem Verständnis heraus, sollte das Programm, wenn dWert nicht eine Gleitkomma-Zahl übergeben wird in die Except-Fkt springen und mir somit ein "Hier" ausgeben. Er meldet mir aber, dass in dem Edit (FEdmanuelleBeschleunigungsEingabe) dies nicht der Fall ist (es steht dort wirklich keine Gleitkomma drin!) was also richtig ist. Wie gesagt, eigentlich erwarte ich eigentlich, dass die Exception nicht auftritt und er mir statt dessen Die Showmessage zeigen sollte.
Kann mir das jemand mal erklären, warum dies in dem Fall so ist?

PS.: ich weiß mit der trystrtofloat könnte ich dieses ganze Problem umgehen, indem ich eine if-Abfrage starte aber wenn ich dies tun würde, dann wäre die try-Except-Abfrage in meinem bisherigen Verständnis der Problematik überflüssig, da ich alles mit if abfragen abfangen kann (in einem gewissen größeren Rahmen sicherlich).

Vielen Dank
BAMatze

TheFrog 29. Apr 2009 13:29

Re: Verständnisfrage zu try-except-finally
 
Kann es sein, dass du unter Tools --> Debugger-Optionen --> Sprach-Exceptions die Option "Bei Delphi-Exceptions stoppen" aktiviert hast und die Anwendung aus der IDE heraus startest?

Hans.

sirius 29. Apr 2009 13:31

Re: Verständnisfrage zu try-except-finally
 
Ergänzung zu roter Kasten:

Du hast aber nicht übersehen, dass beim ausführen des Programmes in der IDE das Programm immer bei jedem Fehler angehalten wird. Erst danach erfolgt eine mögliche Excpetionbehandlung.

Also: Innerhalb der IDE kommt erst der Stop beim Fehler selbst und dann was in Except steht. Außerhalb der IDE passiert nur, was in Except steht.

himitsu 29. Apr 2009 13:33

Re: Verständnisfrage zu try-except-finally
 
Wer dir hier die Exception meldet, ist der Debugger ... starte mal dein Programm außerhalb der Delphi-IDE oder schalte die entsprechenden Meldungen ab.

aber zumindestens im Fertigen Programm (ohne daß es im Debugger läuft) wird die Exception nicht mehr angezeigt.

PS: TryStrToFloat hätte noch einen Vorteil, denn dieses wirft erst garkeine Exception, welcher sich erstmal durch's halbe Programm frißt (Exceptions sind 'ne größere Angelegenheit und da läuft einiges im Hintergrund ab, welches natürlich auch Rechenzeit frißt und dazu noch den Code etwas vergrößert)

BAMatze 29. Apr 2009 13:42

Re: Verständnisfrage zu try-except-finally
 
Ja das Häckchen war es.

Wäre aber jetzt eine Folgefrage: Was sollte man wo setzen? Ich meine in diesem Fall würde ich warscheinlich die trystrtofloat-Abfrage bevorzugen, da ich aufgrund der Kürze des Programmcodes mit keinen weiteren Fehlern rechnen müsste (Der Fehler ist somit qualifizierbar). Gibt es da vieleicht (für einen Anfänger wie mich) so grundsätzliche Regeln für den Einsatz von try-except-finally, die zu einer gewissen Warscheinlichkeit immer greifen, so dass man nur noch die Ausnahmen behandeln muss oder ist das eher eine Philosophy, die sich ein jeder Programmierer oder Benutzer einer Programmiersprache selber erfinden muss?

shmia 29. Apr 2009 13:58

Re: Verständnisfrage zu try-except-finally
 
Du benützt try..except auf eine ganz falsche Art und Weise!!
Früher, als es noch keine Exceptions gab, hat man Fehler fast immer über einen Returncode zurückgeliefert.
Delphi-Quellcode:
function BerechneIrgendwas:integer;
begin
  ...
  if zins < 0.0 then
  begin
    result := ERROR_CODE_ZINS_FALSCH;
    Exit;
  end;
  ...
end;
Man kann dies noch etwas vereinfachen, in dem man als Returncode nur True oder False zurückliefert.
Natürlich ist die Technik einen Fehler über einen Boolean zurückzumelden (so wie du das in TControlerBoard.anaAusgang_einschalten tust) das Schlechteste was man tun kann.
Grund: die Ursache des Fehler bleibt für immer im Dunkeln

Und jetzt kommt die Technik der Exceptions in Spiel.
Jetzt man man sinnvolle Fehlermeldungen zurückliefern, anstatt nur Fehlercodes oder nur die Info "Geht" oder "Geht nicht".
Richtig blöd wird es aber, wenn man eine Exception mit sinnvoller Fehlermeldung (z.B. "COM-Port 1 kann nicht geöffnet werden")
mit try...except abfängt und daraus einen Boolean-Returncode produziert. :wall:

Weiterer Lesestoff:
http://www.delphipraxis.net/internal...ct.php?t=30241

himitsu 29. Apr 2009 14:02

Re: Verständnisfrage zu try-except-finally
 
also wenn dein Programm nach der Exception noch 'ne Weile ordentlich weiterlaufen soll, dann dort, wo du etwas schützen mußt >>> Resourcenschutzblock

Delphi-Quellcode:
// hier Speicher reservieren / etwas sperren oder sonstwas,
// was auf jeden Fall rückgängig gemacht werden muß
Lock; oder X:=GetMem; oder Y:=Z.Create;
try
  //hier was machen
finally
  // und hier den Speicher freigeben oder die Sperre aufheben
  Unlock; oder FreeMem(X); oder Y.Free;
end;
oder wenn du selber auf die Exception reagieren willt, um stattdessen etwas Alternatives zu machen
Delphi-Quellcode:
try
  // mach was
except
  // mach stattdessen was Anderes
end;
Es ist garnicht möglich wirklich auf alles zu reagieren, also besinn dich nur auf das "Nötigste", dann bleibt dein Code auch übersichtlicher.
in nochmalen VCL-Anwendungen (nicht in einer Konsolenanwendung) ist eh nahezu jeder Prozeduraufruf seitens der VCL (also z.B. Ereignisprozeduren) mit einem Try-Except abgesichert, so daß nicht gleich das ganze Programm verreckt, wenn mal was passiert. :angel:


PS: in meinem aktuellen Projekt (Hier im Forum suchenhimXML) fang ich absichtlich fast garkeine Exceptions ab (und wenn, dann wandle ich die meißt in eigene Exceptions um), leite alles nach Außen hin weiter und erzeuge notfalls sogar selber Exceptions.
Ich sorge meist nur mit einem Try-Finally daß möglichst keine Speicherlecks entstehen. (kannst dich da gern mal umsehen)

So kann man im aufrufendem Code besser reagieren und man erfährt auch was und wo es geknallt hat ... denn wenn es knallt, dann hat das 'nen Grund und den gilt es zu finden und zu beheben, anstatt alles unter den Teppisch zu kehren. :angel2:

PSS: meinen Hier im Forum suchenFileSplitter hab ich damals ganz ohne Try-Except/Finally programmiert, denn diese sing garnicht immer nötig, wenn man die Fehler vorher abfängt (also bevor es knallt) und man weiß was man tut und was passieren könnte bzw. was nicht passiert. :angel:

BAMatze 29. Apr 2009 14:36

Re: Verständnisfrage zu try-except-finally
 
Also schonmal ein Dankeschön an shmia und himitsu für die doch recht ausführlichen Erklärungen über try Except.

@shmia
Ich hab mir deinen Lesestoff mal zu Gemüte geführt und es ist auch sehr informativ. Habe auch glaube ich ein paar Prozeduren genommen, wo ich für mich selber festgestellt habe, dass auch wenn die Aufrufe ins Nirvana gehen (z.B. wenn die Karte gar nicht angeschlossen ist) gar keine Exception erzeugen. Bin mir bei diesen Proceduren auch noch nicht sicher, ob ich dann die Exceptions drin lassen sollte oder sie wieder rausnehme.

Habe hier mal ein anderen Programmteil aus dem Projekt genommen und würde gern mal eure Meinung dazu hören, ob sinnvoll oder ob nicht sinnvoll oder vieleicht Verbesserungen möglich wären. Ich bitte dabei zu beachten, dass es sich dabei um meinen ersten Versuch handelt, mit Exceptions umzugehen und Fehlercodes in mein Programm einzubauen.

Delphi-Quellcode:
function TControlerBoard.DLLHandle_zuweisen: boolean;
begin
  //Protokoll.Protokolleingang('ControlerBoard', 'DLLHandle-Fkt');
  Fehlermeldung(300);
  try
    ControlerDLL := TDLL_Datei.create('K8055D.DLL');
    if ControlerDLL.Vorhanden then
      begin
        DLL_Handle := ControlerDLL.Handle;
        result := true;
      end
    else
      begin
        Fehlermeldung(301);
        DLL_Handle := 0;
        result := false;
      end
  except
    Fehlermeldung(302);
    result := false;
  end;
  //Protokoll.Protokollausgang('ControlerBoard', 'DLLHandle-Fkt');
end;

function TControlerBoard.DLLFunktionen_laden: boolean;
begin
  //Protokoll.Protokolleingang('ControlerBoard', 'DLL-Fkt laden');
  try
    if DLL_Handle <> 0 then
      begin
        @OpenDevice := GetProcAddress(DLL_Handle, 'OpenDevice');
        @CloseDevice := GetProcAddress(DLL_Handle, 'CloseDevice');
        @ClearAllAnalog := GetProcAddress(DLL_Handle, 'ClearAllAnalog');
        @ClearAllDigital := GetProcAddress(DLL_Handle, 'ClearAllDigital');
        @ClearAnalogChannel := GetProcAddress(DLL_Handle, 'ClearAnalogChannel');
        @ClearDigitalChannel := GetProcAddress(DLL_Handle, 'ClearDigitalChannel');
        @OutputAnalogChannel := GetProcAddress(DLL_Handle, 'OutputAnalogChannel');
        @SetDigitalChannel := GetProcAddress(DLL_Handle, 'SetDigitalChannel');
        @ReadDigitalChannel := GetProcAddress(DLL_Handle, 'ReadDigitalChannel');
        result := true;
      end
    else
      begin
        Fehlermeldung(303);
        result := false;
      end
  except
    Fehlermeldung(304);
    result := false;
  end;
  //Protokoll.Protokollausgang('ControlerBoard', 'DLL-Fkt laden');
end;

function TControlerBoard.Initialising:boolean;
begin
  try
    if (DLLHandle_zuweisen = true) and (DLLFunktionen_laden = true) then
      begin
        OpenDevice(0);
        ClearAllDigital;
        {Liste der einzuschaltenen Geräte per Funktion hier einfügen}
        V_Tische_Stromversorgung_einschalten;
        P_Tisch_Stromversorgung_einschalten;
        Spleissgeraet_einschalten;
        result := true;
      end
    else
      begin
        Fehlermeldung(305);
        result := false;
      end
  except
    Fehlermeldung(306);
    result := false;
  end;
end;
Ok ich denke, da ich fast alle Units ähnlich wie diese aufgebaut habe, ist die Vorgehensweise erkennbar. Die "Fehlermeldung(...)" ist dabei für mich eine Meldefunktion an eine Fehlerklasse, die anhand der Nummer den auftretenden Fehler zum Teil genau aber in einigen Fällen auch nur in einem gewissen Rahmen qualifiziert. In der Fehler-Klasse werden die übergebenen Nummern interpretiert und dann in eine Fehler-Log-Datei eingeschrieben. Bisher bin ich mit der Methode eigentlich zu frieden, da ich darüber mein Programm auch wenn bestimmte Geräte (wie z.B. die Controler-Board-Karte) nicht angeschlossen sind, starten kann und über den Status im Programm der Bediener mitbekommt, was genutzt werden kann und was er vieleicht doch nochmal einschalten muss oder was nicht funktioniert.

Über konstruktive Kritik würde ich mich sehr freuen.

BAMatze 29. Apr 2009 17:06

Re: Verständnisfrage zu try-except-finally
 
Keiner eine Meinung?

DeddyH 29. Apr 2009 17:18

Re: Verständnisfrage zu try-except-finally
 
Exceptions kannst Du nur da abfangen, wo auch welche geworfen werden. GetProcAddress z.B. gehört nicht dazu, bei Misserfolg ist der Funktionszeiger dann eben nil. Außerdem bedeutet Exception Ausnahme, d.h. das sind Fehler, die nur unter besonders ungünstigen Bedingungen auftreten können (Abbruch der Netzwerkverbindung, nicht genügend Festplattenplatz, kein Datenträger im Laufwerk oder etwas in der Art) und auf die Du keinen Einfluss hast. Alle durch Dich vermeidbaren Fehlerquellen solltest Du schon programmatisch abfangen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:43 Uhr.
Seite 1 von 2  1 2      

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