Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi try ... except --> wann verwenden ??? (https://www.delphipraxis.net/96891-try-except-wann-verwenden.html)

Christian18 1. Aug 2007 11:16


try ... except --> wann verwenden ???
 
Hallo,

ich habe ein kleines Projekt, wo ich alle Fehler mit try ... except abfangen möchte. Nun stellt sich mir die Frage wann man es verwenden.

Wenn man nur ein Label beschriftet, dann soch sicherlich nicht oder? Wann verwendet Ihr try ... except???

MFG Chris

Matze 1. Aug 2007 11:22

Re: try ... except --> wann verwenden ???
 
Hallo,

ich würde es da nutzen, wo Fehleingaben vom Benutzer Fehler verursachen würden bzw. allgemein da, wo Fehler leicht auftreten können. Wenn möglich solltest du jedoch try-except weitmöglich umgehen und lieber per if-Abfragen prüfen, ob etwas funktioniert hat oder nicht, finde ich. Das ist je nach Situation natürlich unterschiedlich.
Alle Fehler abzufangen wäre ganz simpel mittels TApplicatioEvents (oder wie das genau heißt) möglich, doch Fehler nur zu unterdrücken ist nicht ratsam.

Luckie 1. Aug 2007 11:25

Re: try ... except --> wann verwenden ???
 
Da gibt es einen guten Artikel: Exception Handling for Fun and Profit.

Christian18 1. Aug 2007 11:45

Re: try ... except --> wann verwenden ???
 
danke,

ihr habt mir sehr geholfen. Besonders luckie xD

Dezipaitor 1. Aug 2007 12:01

Re: try ... except --> wann verwenden ???
 
Delphi-Quellcode:
try
 XY;
except
end;
Für solche Fälle musste ich feststellen, dass diese Art von Exceptionhandling Speicherlöcher erzeugen kann.

SirThornberry 1. Aug 2007 12:27

Re: try ... except --> wann verwenden ???
 
Zitat:

Zitat von Dezipaitor
Delphi-Quellcode:
try
 XY;
except
end;
Für solche Fälle musste ich feststellen, dass diese Art von Exceptionhandling Speicherlöcher erzeugen kann.

Das hängt davon ab was XY ist. Und wenn da ein Speicherloch entsteht liegt es daran das nach dem exceptblock wohl etwas vorher reserviertes nicht frei gegeben wird.

ptown67 1. Aug 2007 12:31

Re: try ... except --> wann verwenden ???
 
Hier ein gutes Beispiel:

Code:
uses
  URLMon;

procedure TForm1.Button1Click(Sender: TObject);
var
  Datei,Ziel:PChar;
begin
  Label1.Caption := 'Download gestartet';
  try
    Datei := 'http://www.DieSeite/DieDatei.zip';
    Ziel := 'C:\Windows\Desktop\DieDatei.zip';
    UrlDownloadToFile(nil, Datei, Ziel, 0, nil);
    Label1.Caption := 'Download beendet';
  except
    showmessage('Download abgebrochen');
  end;
end;
Gruß Freeman

Luckie 1. Aug 2007 12:33

Re: try ... except --> wann verwenden ???
 
Gerade das ist ein schlechtes Beispiel, weil API-Funktionen in der Regel keine Exceptions werfen. Zu dem hat UrlDownloadToFile einen Rückgabewert, den man auswerten kann.

Dezipaitor 1. Aug 2007 12:51

Re: try ... except --> wann verwenden ???
 
So ich hab mal ein Beispiel für Exception (ob gut oder schlecht?)

Delphi-Quellcode:

 {@Name function generates an audit message in the security event log.
         For a detailed information see MSDN : [url]http://msdn2.microsoft.com/en-gb/library/aa379305.aspx[/url]

         If you want to enable audit functions the calling process (not thread token!) needs the SeAuditPrivilege privilege.
         Per default only services have this privilege. However it can be enabled in group policy editor : "gpedit.msc" manager (under xp)
           Computer configuration -> Windows settings -> security settings -> local policies -> audit policy
            enable (success/failure) policy : audit privilege
          The parameter AccessGranted is linked with the type of policy - success or failiure.
          ([url]http://www.nemesisblue.info/images%5Cgpedit1.gif[/url])

         The audit event can be seen in the event viewer in security leaf.

         @param(ClientToken is the token to be used in audit log. )

         @raises(ESMPrivilegeNotFoundException will be raised if the process token does not have the privilege : SE_AUDIT_NAME)
         @raises(ESMWinCallFailedException will be raised if the winapi call to PrivilegedServiceAuditAlarm failed.)
         @raises(ESMInvalidTokenHandle will be raised if the parameter ClientToken is nil)
         }
class procedure TSecurityToken.PrivilegedServiceAuditAlarm(SubsystemName, ServiceName : TString; ClientToken : TSecurityToken;
                                        Privileges : TPrivilegeSet; AccessGranted :Boolean);


var pPriv : JwaWinNT.PPRIVILEGE_SET;
    privs : TPrivilegeSet;

    primToken : TSecurityToken;
    bOldAuditPriv : Boolean;
begin
  if not Assigned(ClientToken) then
    raise ESMInvalidTokenHandle.CreateFmtEx('ClientToken must not be nil.', 'PrivilegedServiceAuditAlarm',ClassName,'USM_Token.pas', 0,true,[]);


  {PrivilegedServiceAuditAlarm checks the process token for the needed privilege SE_AUDIT_NAME.
   So we open it here.
   The thread that calls this function does not need that privilege.

   We open the token with minimal access.

  }
  primToken := TSecurityToken.CreateTokenByProcess(0,
                TOKEN_READ or
                TOKEN_QUERY or
                TOKEN_ADJUST_PRIVILEGES or
                TOKEN_AUDIT_SUCCESS_INCLUDE or TOKEN_AUDIT_SUCCESS_EXCLUDE or
                TOKEN_AUDIT_FAILURE_INCLUDE or TOKEN_AUDIT_FAILURE_EXCLUDE);

  {first we try to get status of SE_AUDIT_NAME privilege.
   Maybe the process has not the privilege?

   We save the privilege status for later resetting.
  }
  try
    bOldAuditPriv := primToken.PrivilegeEnabled[SE_AUDIT_NAME];
  except
    on E1 : ESMPrivilegeNotFoundException do
    begin
      //do special things here - for future
      primToken.Free;
      raise; //notify caller
    end;

    On E2 : Exception do
    begin
      //free in every case
      primToken.Free;
      raise; //but re-raise
    end;
  end;

  //not enable privilege
  primToken.PrivilegeEnabled[SE_AUDIT_NAME] := true;

  //now we set all privileges of the client token, so they will be shown in the audit log message
  privs := ClientToken.GetTokenPrivileges;
  pPriv := privs.Create_PPRIVILEGE_SET;

  if not {$IFDEF SM_UNICODE}PrivilegedServiceAuditAlarmW{$ELSE}PrivilegedServiceAuditAlarmA{$ENDIF}
        (TPChar(SubsystemName), TPChar(ServiceName), ClientToken.TokenHandle,pPriv^, AccessGranted)  then
  begin
    //reset privilege to old status
    //free everything before raise exception
    primToken.PrivilegeEnabled[SE_AUDIT_NAME] := bOldAuditPriv;
    privs.Free_PPRIVILEGE_SET(pPriv);
    privs.Free;
    //free token
    primToken.Free;
    raise ESMWinCallFailedException.CreateFmtEx('Call to PrivilegeCheck failed.', 'PrivilegedServiceAuditAlarm',ClassName,'USM_Token.pas', 0,true,[]);
  end;

  //reset privilege to old status
  primToken.PrivilegeEnabled[SE_AUDIT_NAME] := bOldAuditPriv;
  privs.Free_PPRIVILEGE_SET(pPriv);
  privs.Free;
  //free token
  primToken.Free;
end;

Luckie 1. Aug 2007 12:55

Re: try ... except --> wann verwenden ???
 
Dein primToken wird im Falle eines Fehlers in der Methode nicht freigegeben. Da gehört noch ein try-finally-Block drumrum.

smudo 1. Aug 2007 13:00

Re: try ... except --> wann verwenden ???
 
Ich vermisse unter Delphi einen Try-Except-Finally-End Block. Dann wären Speicherlecks recht komfortabel auszuschließen. C# hat sowas.

alzaimar 1. Aug 2007 13:05

Re: try ... except --> wann verwenden ???
 
Ich finde, man sollte Try ... Except Blöcke dann verwenden, wenn im Normalfall nichts passiert, aber eine Ausnahme (nichts anderes bedeutet ja 'Exception') gesondert behandelt werden sollte.

Zitat:

Zitat von Matze
ich würde es da nutzen, wo Fehleingaben vom Benutzer Fehler verursachen würden bzw. allgemein da, wo Fehler leicht auftreten können. Wenn möglich solltest du jedoch try-except weitmöglich umgehen und lieber per if-Abfragen prüfen, ob etwas funktioniert hat oder nicht, finde ich. Das ist je nach Situation natürlich unterschiedlich.

Grausam, dabei kommt sehr unübersichtlicher Code heraus:
Delphi-Quellcode:
If ActionA=aSuccess Then
  If ActionB = Success Then
    If ActionC = Success Then
      If ActionD = Success Then
         .....
      else
        ....
   else
 ...
Oder auch
Delphi-Quellcode:
aResult := ActionA;
If aResult<>Success Then Exit;
aResult := ActionB;
If aResult<>Success Then Exit;
aResult := ActionC;
If aResult<>Success Then Exit;
aResult := ActionD;
If aResult<>Success Then Exit;
vs.
Delphi-Quellcode:
Try
  ActionA;
  ActionB;
  ActionC;
  ActionD;
Except
  Raise Exception.Create('Bei der Abarbeitung der Aktionen ist ein Fehler aufgetreten');
End;
Also, schreib mal übersichtlicheren und robusten Code ohne Try...Except.

Es ist natürlich beim Design und Debuggen etwas nervig, wenn einem Exceptions um die Ohren fliegen. Aber erstens kann man das ausschalten und zweitens ist es ja eine Ausnahme, die eben nur in Ausnahmefällen vorkommen sollte.

Programmfehler würde ich mit Assert-Anweisungen vermeiden, Logische Prüfungen von Eingaben vermutlich über einen Parser / DEA analysieren und bei einem Fehler eine Exception 'EUserInputException' schmeissen, die die genaue Ursache und Position beinhaltet.

Zum Beispiel vom Dezipaitor. Variante A (Wenn der Fehler weitergereicht werden soll);
Delphi-Quellcode:
MyOBject:= TMyObject.Create;
Try
  Try
    MyObject.CriticalMethod;
  Except
    On E:ESomeException Do Begin
      HandleSomeException (E);
      Raise
    End
  End
Finally
  MyObject.Free;
End;
Und wenn nicht:
Delphi-Quellcode:
MyObject:= TMyObject.Create;
Try
  MyObject.CriticalMethod;
Except
  On E:ESomeException Do
    HandleSomeException (E);
End;
MyObject.Free;
Letzteres ist die sog. 'Halts Maul' Variante, die man durch einen überflüssigen Try..Finally Block kapseln kann:
Delphi-Quellcode:
MyObject:= TMyObject.Create;
Try
  Try
    MyObject.CriticalMethod;
  Except
    On E:ESomeException Do
      HandleSomeException (E);
  End;
Finally
  MyObject.Free;
End;

smudo 1. Aug 2007 13:11

Re: try ... except --> wann verwenden ???
 
Beim Befüllen einer Caption halte ich es nicht sinnvoll (was soll dabei schief gehen und was soll ich anschließend mit der abgefangenen Exception machen)
Ich setze es immer nur dann ein, wenn ich nach einer schiefgelaufenen Aktion etwas unternehmen muss. Z.B. ein Rollback
Delphi-Quellcode:
StartTransaction
try
 ...
except
  RollBack;
  raise;
end;
Commit;

alzaimar 1. Aug 2007 13:48

Re: try ... except --> wann verwenden ???
 
[Klugscheiss]Da jedoch das Commit konzeptionell zur Aktion gehört, sollte man es auch in den Block packen [/Klugscheiss]
Delphi-Quellcode:
StartTransaction
try
...
  Commit;
except
  RollBack;
  raise;
end;
Es tut aber eigentlich Nichts zur Sache.

dajuhsa 1. Aug 2007 13:56

Re: try ... except --> wann verwenden ???
 
Zitat:

Zitat von smudo
Ich vermisse unter Delphi einen Try-Except-Finally-End Block. Dann wären Speicherlecks recht komfortabel auszuschließen. C# hat sowas.

wie wärs mit
Delphi-Quellcode:
try
  ...
  try
    ...
  except
    ...
  end;
finally
  ...
end;

Matze 1. Aug 2007 13:58

Re: try ... except --> wann verwenden ???
 
Zitat:

Zitat von alzaimar
Grausam, dabei kommt sehr unübersichtlicher Code heraus [...]

Zitat:

Zitat von Matze
Das ist je nach Situation natürlich unterschiedlich.

Ich ging nun von Fehleingaben aus, die Christian angesprochen hat. Da würde ich persönlich beispielsweise eher TryStrToInt nutzen als einen try-except-Block. Aber das bleibt jedem selbst überlassen.
Bei komplexeren Strukturen, wie du sie ansprichst, ist das natürlich nicht sonderlich sinnvoll, auf try-except zu verzichten.

squetk 1. Aug 2007 20:18

Re: try ... except --> wann verwenden ???
 
Zitat:

Zitat von alzaimar
[Klugscheiss]Da jedoch das Commit konzeptionell zur Aktion gehört, sollte man es auch in den Block packen [/Klugscheiss]
Delphi-Quellcode:
StartTransaction
try
...
  Commit;
except
  RollBack;
  raise;
end;

Sehe ich nicht so, weil zwischen try und except doch Anweisungen stehen müssten, die im Fehlerfalle ein Rollback auslösen sollen. Das kann ich mir beim Commit als "Gegenstück" zum Rollback nicht vorstellen. Sollte beim Commit wider Erwarten eine Exception auftreten, wäre ein Rollback auch sinnlos.

Christian Seehase 1. Aug 2007 22:45

Re: try ... except --> wann verwenden ???
 
Moin squetk,

Zitat:

Zitat von squetk
Sollte beim Commit wider Erwarten eine Exception auftreten, wäre ein Rollback auch sinnlos.

Das ist zwar richtig, aber der try/except-Block kapselt ja den Normalfall, der dann mit Commit abgeschlossen würde, womit Commit logisch in den Block gehört.

alzaimar 2. Aug 2007 05:34

Re: try ... except --> wann verwenden ???
 
Weiterhin muss - bei korrekter ACID-Implementierung - das Rollback auch ein fehlerhaftes Commit rückgängig machen können.
Zitat:

Zitat von Matze
Ich ging nun von Fehleingaben aus, die Christian angesprochen hat. Da würde ich persönlich beispielsweise eher TryStrToInt

Nach nochmaligem Lesen interpretiere ich Deine Äußerungen auch so. Mea Culpa.

smudo 2. Aug 2007 11:06

Re: try ... except --> wann verwenden ???
 
Das fänd ich jetzt mal interessant.
Was kann dazu führen, dass ein Commit fehlschlägt - was ein Rollback reparieren könnte?
Und was ist ACID? Ich kenn nur die Musikrichtung :dancer2:

Luckie 2. Aug 2007 11:08

Re: try ... except --> wann verwenden ???
 
Bitte erstell dazu einen neuen Beitrag. Da gehört hier nicht unbedingt rein.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:27 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