AGB  ·  Datenschutz  ·  Impressum  







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

ersetzt try..except begin..end?

Ein Thema von messie · begonnen am 20. Sep 2007 · letzter Beitrag vom 20. Sep 2007
Antwort Antwort
Seite 3 von 3     123   
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#21

Re: ersetzt try..except begin..end?

  Alt 20. Sep 2007, 12:03
Zitat:
Ergänzung: nicht nur! Innerhalb des Except / End Blockes ist die globale Variable ExceptObject gültig und diese enthält die aktuelle Exception.
Das ist gefährlich diese Annahme zu unterstellen.

Wir wissen: ExceptObject ist eine globale Variable. Ist sie auch eine Threadeigene globale Variable -> threadvar ?

Wenn nicht kann innerhalb deiner verschachtelten IF Abfragen das ExceptObject als globale Variable durch eine Exception innerhalb eines parallelen Threads verändert werden.

Man sollte also wirklich

Delphi-Quellcode:
try
except
  on E: Exception do
    if E is EAbort then ... else
      if E is EInOutError then ...
        else reraise;
end;
benutzen. In diesem Moment verhält sich das on E: Exception do wie ein with Variable do Anweisung. Der Compiler wird dann in der lokalen Variable E das aktuelle Exception Object zur Verfügung halten, statt bei jeder IF Abfrage auf ein globales Object zuzugreifen. Davon abgesehen ist das SEH unter Windows Stackbasiert und mit der Abfrage on E: Exception do greifen wir nur auf diesen Stack und damit Threadbezogen auf das einzigste gültige Exception Object zu. Die globale Variable ExceptObject ist also eher eine Krücke damit bestimmte Objekte wie TApplication ein eigene Handling von Exception machen können.

Gruß Hagen
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#22

Re: ersetzt try..except begin..end?

  Alt 20. Sep 2007, 12:07
@messie: Weil der Konstruktor fehlschlagen kann, und dann wäre da nichts zum freigeben. Weiterhin stimmt der Kontext nicht: Der Try..Finally-Block soll ja gerade die Verwendung des OPbjektes schützen und nicht die Instantiierung selbst.

Richtig wäre es so:
Delphi-Quellcode:
Try
  Obj := TMyObect.Create;
  Try
    Obj.Foobar
  Finally
    Obj.Free
Finally
  Showmessage('Ach Du scheisse, noch nich mal Create funzt.')
End;
@NegaH: Ich mag es aber in grün lieber:
Delphi-Quellcode:
Try
...
Except
  On E:EThisException Do Begin
    HandleThisException(E);
  End;
  On E:EThatException Do Begin
    HandleThatException (E);
  End;
  On E:Exception Do Begin
    HandleAnyOtherException (E);
  End;
End;
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#23

Re: ersetzt try..except begin..end?

  Alt 20. Sep 2007, 12:08
@Messie:

Zitat:
Warum wäre das falsch? Es ist nicht dieselbe Funktion aber warum nicht?
Überlege mal ab wann die Variable Object wirklich ein gültiges Object enthalten kann.

Erst nachdem der Konstruktor erfolgreich zurückkehrt.

Und was würde passieren wenn der Konstruktor eine Exception auslösst ? Zb. wegen's Speichermangel oä. ?
Dann würden wir sofort im finally end; Block landen. Ist dann die Variable Object wirklich initialisert wurden ?
Nein, in Object würde irgendwas stehen, also vorherige Daten aus dem Stack oder einem CPU Register. Wozu führt dies ?
Das bei Object.Free; wir ein Object freigeben würden das garnicht also solches existent ist. Nur wenn Object durch dummen Zufall nil =$00000000 wäre würde es keine Zugriffsveretzung geben. Dieser Fall tritt mit exakt 1/2^32 Wahrscheinlichkeit ein, also sehr unwahrscheinlich.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#24

Re: ersetzt try..except begin..end?

  Alt 20. Sep 2007, 12:15
@Alzaimar:

Zitat:
Delphi-Quellcode:
try
...
Except
  On E:EThisException Do Begin
    HandleThisException(E);
  End;
  On E:EThatException Do Begin
    HandleThatException (E);
  End;
  On E:Exception Do Begin
    HandleAnyOtherException (E);
  End;
End;
Ohne jetzt über Stilfragen diskutieren zu wollen, aber wir können das mal vergleichen:

Delphi-Quellcode:
try
except
  on E: Exception do
    if E is EThisException then HandleThisException(E) else
      if E is EThatException then HandleThatException(E)
        else HandleAnyException(E);
end;
1.) Lesbarkeit, bzw. Explizität dessen was man schreibt, nichts ist zuviel oder zu wenig umschrieben.
2.) ob man on E: XYZ do abfragt oder E is XYZ ist egal, dahinter wird der Compiler den gleichen Code erzeugen, für die Klassentyp Abfrage.
3.) Programablaufpfad, bei deiner Lösung fragst du unnötigerweise mit wesentlich höherer Wahrscheinlichkeit die Exception Klasse ab. Bei meinem wird auf grund der kaskadierten IF Abfrage die Wahrscheinlichkeit das zb. HandleAnyException() aufgerufen wird drastisch reduziert das die Wahscheinlichkeiten für EThisException und ETahtException davon abzuziehen sind.
Mein Vorschlag ist also effizenzter.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#25

Re: ersetzt try..except begin..end?

  Alt 20. Sep 2007, 12:20
Es ginge glaub ich aus so

Delphi-Quellcode:
try
except
  on E: EThisException do HandleThisException(E) else
    on E: EThatException do HandleThatException(E) else
      on E: Exception do HandleAnyException(E);
end;
Das hat dann aber eine Klassenabfrage in der letzten Zeile mehr als die IF Abfrage.
Zudem wird bei jedem on E: XYZ do erneut aus dem SEH Frame das Exception Object geladen werden müssen. Das bedeutet 2 indirekte Specherzugriffe mehr pro dieser Abfrage.

Die IF Abfrage Methode holt also nur einmalig E aus dem SEH Frame im Stack. Danach verhalten sich die IF Abfragen wie in einem with E do Block.

Aus meiner Sicht also effizienter und auch leichter lesbar. Die Lesbarkeit liegt aber oft im Auge des Betrachters, die entstehdne Funktionalität aber nicht. Und exakt in diesem Punkt unterscheiden sich unsere Lösungen beträchtlich.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#26

Re: ersetzt try..except begin..end?

  Alt 20. Sep 2007, 12:58
Wir können das mal herleiten.

Wir wissen das wir uns in einem absolut logischen und abgeschlossenen System bewegen, auf einem Computer und in der Syntax der Sprache Delphi.

Delphi-Quellcode:
try
except
  on E: Exeption do
end;
was macht dieses,

on E: Exception do

mal ausgedrückt in Delphi, denn eigentlich ?

Delphi-Quellcode:
try
except
  with Hole_Exception_Object_Aus_SEH in variable E do
    if E is Klassentyp then
end;
Nun schreiben wir die Abfrage wie sie Alzaimar benutzt um

Delphi-Quellcode:
try
except
  with Hole_Exception_Object_Aus_SEH in variable E do
    if E is EThisException then
    begin
      HandleThisException(E);
    end;
// 1.)
  with Hole_Exception_Object_Aus_SEH in variable E do
    if E is EThatException then
    begin
      HandleThatException(E);
    end;
// 2.)
  with Hole_Exception_Object_Aus_SEH in variable E do
    if E is Exception then
    begin
      HandleAnyException(E);
    end;
end;
Was wissen wir am Punkt 1.) ?
Wir wissen das falls die vorherige Abfrage zutreffen würde wir die Abfrage in 1.) einsparen könnten. Denn wenn E vom Typ EThisException ist dann kann sie nicht vom Typ EThatException mehr sein.

Aber stellen wir uns mal vor EThisException wäre von EThatException abgeleitet ?
Dann würde die erste Abfrage zutreffen und die bei 1.) und 2.) aber auch ?
Macht es Sinn, bzw. ist es sogar beabsichtigt das man dann zwei bzw. sogar drei Behandlungsroutinen für eine Exception ausführt ?
Meistens, ja fast immer, macht sowas keinen Sinn.

Wir können also vereinfachen und sogar eventuelle logische Fehler beseitigen.

Delphi-Quellcode:
try
except
  with Hole_Exception_Object_Aus_SEH in variable E do
    if E is EThisException then
    begin
      HandleThisException(E);
    end else
      with Hole_Exception_Object_Aus_SEH in variable E do
        if E is EThatException then
        begin
          HandleThatException(E);
        end else
          with Hole_Exception_Object_Aus_SEH in variable E do
            if E is Exception then
            begin
              HandleAnyException(E);
            end;
end;
Wir kaskadieren die IF Anfragen und verkürzen so den Programablaufpfad. Der Code wird dadurch sogar noch schneller ausgeführt.

Nun stellen wir fest das die "Funktion" Hole_Exception_Object_Aus_SEH dreimalig aufrufen. Hinter jedem dieser Aufrufe versteckt sich produzierter Code, davon abgesehen ist es auch redundant.

Wir vereinfachen

Delphi-Quellcode:
try
except
  with Hole_Exception_Object_Aus_SEH in variable E do
    if E is EThisException then
    begin
      HandleThisException(E);
    end else
      if E is EThatException then
      begin
        HandleThatException(E);
      end else
        if E is Exception then
        begin
          HandleAnyException(E);
        end;
end;
Wir stellen fest das die vielen begin end Blöcke überflüssige Redundanz darstellen. Das alles müssen wir beim Lesen mit den Augen erfassen, im Hirn übersetzen, und das für Nichts. Es ist demzufolge nicht explizit.

wir vereinfachen

Delphi-Quellcode:
try
except
  with Hole_Exception_Object_Aus_SEH in variable E do
    if E is EThisException then HandleThisException(E) else
      if E is EThatException then HandleThatException(E) else
        if E is Exception then HandleAnyException(E);
end;
Wir wissen das alle Exception Klassen von der Basisklasse Exception abgeleitet werden. Also ist die letzte IF Abfrage überflüssig, sie ist immer WAHR.

wir vereinfachen

Delphi-Quellcode:
try
except
  with Hole_Exception_Object_Aus_SEH in variable E do
    if E is EThisException then HandleThisException(E) else
      if E is EThatException then HandleThatException(E)
        else HandleAnyException(E);
end;
Wir haben vorher die on E: Exception do Syntax in eine logische Form gebracht die uns besser erklärt was da vor sich geht. Diesen Abstraktionsschritt machen wir rückgängig.

Delphi-Quellcode:
try
except
  on E: Exception do
    if E is EThisException then HandleThisException(E) else
      if E is EThatException then HandleThatException(E)
        else HandleAnyException(E);
end;
Wir resümieren: Das zu lösende Problem wurde in der Delphi Syntax auf ein nicht mehr reduzierbares Maß verkürzt. Jede weitere Reduktion würde die angestebte und sinnvolle Funktionalität verändern.

Anders ausgedrückt: es ist eben keine Stilfrage wie man was schreibt sondern eine logisch herleitbare und sinnvoll auf ein notweniges Maß reduzierbare Aufgabe des Programmierers. Die Explizität in unseren Sourcezeilen ist also eine logische Notwendigkeit damit wir nur das exakt umschreiben was auch minimal notwendig ist um ein Problem zu lösen. Wer als Programmierer meint er müsste aus modischen Gründen es nicht so handhaben der kann defakto eben nicht programmieren. Gut das sind harte Worte, unfair vielleicht, aber im Grunde absolut richtig. Ein guter Stil zeichnet sich also dadurch aus das er explizit ist.
Jede Weigerung es nicht so zu handhaben kann demzufolge nicht mehr auf logischen Gründen basierend untermauert werden. Es sind meistens emotionale Vorlieben, Sturheit, nicht Lernfähigkeit, aus Prinzip oder Gewohnheiten, aber garantiert nicht überlegtes Denken. Es stellt sich die Frage: Was machen den Programmierer den ganzen Tag lang ?

Gruß Hagen
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#27

Re: ersetzt try..except begin..end?

  Alt 20. Sep 2007, 14:25
Hallo Hagen,

ich habe mir einmal die Mühe gemacht, beide Lösungen mit dem Debugger schrittweise zu durchlaufen. Bei dem von alzaimar vorgeschlagenen Code lande ich (nach dem Fehlerdialog) direkt im Rumpf der passenden on-Anweisung. Im Anschluß an die Fehlerbehandlung erfolgt ein Sprung zum Ende der try-Anweisung, wo das Exception-Objekt über DoneExcept aufgelöst wird. Bei deiner Lösung erfolgt der Sprung zur einzigen on-Anweisung, von dort aus wird über eine Folge von isClass-Aufrufen der passende Handler gesucht. Die Abläufe in Windows (Kernel32 und ntdll) sind bei beiden Lösungen identisch. Sollte deine Lösung dennoch effizienter sein? Mache ich vielleicht einen Denkfehler?

Getestet habe ich übrigens mit Delphi 6 - mit und ohne Optimierung.

Gruß Hawkeye
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#28

Re: ersetzt try..except begin..end?

  Alt 20. Sep 2007, 17:33
Gut jetzt kommt der unangenehme Part für mich.

Zitat von Delphi 5 Hilfe:
Im folgenden Beispiel sind drei Behandlungsroutinen definiert. Die erste behandelt Divisionen durch Null, die zweite Überläufe, und die dritte alle anderen mathematischen Exceptions. Der Typ EMathError ist zuletzt aufgeführt, da er der Vorfahr der anderen beiden Exception-Klassen ist. Würde er an erster Stelle genannt, käme es nie zu einem Aufruf der beiden anderen Routinen.
Delphi-Quellcode:
try

    ...
except
     on EZeroDivide do HandleZeroDivide;
     on EOverflow do HandleOverflow;
     on EMathError do HandleMathError;
end;
Vor dem Namen der Exception-Klasse kann optional ein Bezeichner angegeben werden. Dieser Bezeichner dient in der auf on...do folgenden Anweisung zum Zugriff auf das Exception-Objekt. Der Gültigkeitsbereich des Bezeichners ist auf die Anweisung beschränkt.
Im Falle des Exceptionshandling stimmt meine, für obige schrittweise Herleitung wie man logisch den Source auf eine Explizität reduzieren sollte, nicht.

Tatsächlich ist es so das Delphi im Grunde schon selbstständig alle on E: XYZ do Konstrukte syntaktisch als case of Abfrage umsetzt. Egal wie man es also schreibt es ist vergleichbar mit dem hier

Delphi-Quellcode:
try
except
  case Exception_Object_Type of
    EZeroDivide: JandleZeroDivide;
    EOverflow: HandleOverflow;
    EMathError: HandleMathError;
  end;
end;
dumerweise wird darauf zumindestens in der Delphi 5 Hilfe nicht explizit hingeweisen, ist aber keine Begründung dafür das ich falsch lag. Nicht destrotrotz verliert meine "Anleitung" dadurch nicht an allgemeiner Gültigkeit. In diesem speziellen Falle bin ich aber tatsächlich auf die syntaktischen Eigentümlichkeiten der Excpetionbehandlung herein gefallen. Man lernt halt doch nie aus

Übrigens habe ich es selber auch noch mal getestet und mir den erzeugten Code angeschaut. Hawkeye's du hast also Recht.

Gruß Hagen
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


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 19:08 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