AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Warum zeigt Application.ShowException(..) die INNERSTE?

Warum zeigt Application.ShowException(..) die INNERSTE?

Ein Thema von Der schöne Günther · begonnen am 24. Aug 2015 · letzter Beitrag vom 24. Aug 2015
Antwort Antwort
Der schöne Günther

Registriert seit: 6. Mär 2013
6.160 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

Warum zeigt Application.ShowException(..) die INNERSTE?

  Alt 24. Aug 2015, 10:22
Delphi-Version: XE7
Das macht doch irgendwie keinen Sinn. Folgendes Beispiel:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
resourcestring
   errorMsg = 'The calculation failed';
var
   divisor: Single;
   result: Single;
begin
   divisor := 0.0;
   try
      result := System.Pi() / divisor;
   except
      Exception.RaiseOuterException(
         EProgrammerNotFound.Create(errorMsg)
      );
   end;
end;
TApplication.ShowException(..) ist folgendermaßen definiert:
Delphi-Quellcode:
procedure TApplication.ShowException(E: Exception);
var
  Msg: string;
  SubE: Exception;
begin
  Msg := E.Message;
  while True do
  begin
    SubE := E.GetBaseException;
    if SubE <> E then
    begin
      E := SubE;
      if E.Message <> 'then
        Msg := E.Message;
    end
    else
      Break;
  end;
[...]
Was macht das für einen Sinn dem Benutzer "Floating Point division by Zero" statt "The calculation failed" anzuzeigen? Das ist doch grade der Sinn von geschachtelten Exceptions, dass ich hier sagen kann, was allgemein falsch lief, und nicht welches spezielle Byte umgefallen ist.

Erleuchtet mich.
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.070 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Warum zeigt Application.ShowException(..) die INNERSTE?

  Alt 24. Aug 2015, 11:54
Na, zumindest bist du nicht der erste, der sich wundert:

http://eurekalog.blogspot.de/2010/05...09-and_05.html
Zitat:
Anyway, in both examples we leak important information: an information about previous exception, which can give us hints to the problem. And it is when nested exceptions appears.

The new exception class (whoa, that sure took a lot of time, but I should introduce newbies to nested exceptions after all) have InnerException and BaseException properties. Both properties are set (managed) by SysUtils unit automatically, you don't need to fill them manually. So, you can read and use them. InnerException property stores the previous exception. BaseException stores exception with most nested level - i.e. the very first exception, which started this exception chain. If there are only two exceptions in the chain (old and new, as in examples above), then InnerException will be equal to BaseException. If there is only one exception (i.e. there is no nested exception at all) - then both properties will be equal to nil.

Nested exceptions, however, aren't saved by default. In order to save nested exception, you need to raise new exceptions via Exception.RaiseOuterException (Delphi's style) or Exception.ThrowOuterException (C++ Builder's style). For example:

Delphi-Quellcode:
procedure TSomeClass.SaveToStream(const AStream: Stream);
begin
  try
    // ... saving instance to stream here
  except
    Exception.RaiseOuterException(ESomeClassSaveError.Create('Error saving data to stream'));
  end;
end;
After executing this code, we will get exception of ESomeClassSaveError class, which will have non-nil InnerException property (and BaseException too), which, in turn, will contain original exception (EStreamError or whatever it was).

In the second example (the one with exception in destructor) we still get InnerException = nil, cause RaiseOuterException isn't used anywhere.

How this support of nested exceptions affects error messages? Well, Message property didn't changed - it's a message of current exception only. So, any code, which isn't awared about nested exceptions, will show only message of the last exception. You can use ToString method of Exception class to show all messages from all exceptions - each exception will be on new line (obviously, ToString will be equal to Message property in case of single exception in the chain).

On the other side, Application.ShowException method looks a bit strange: this method shows message from BaseException - I suppose that it's not what you want (see our first example). That's why I think that you may want to make your own Application.OnException event handler to change this behaviour. For example:

Delphi-Quellcode:
procedure TForm1.ApplicationEvents1Exception(Sender: TObject; E: Exception);
var
  Msg: String;
begin
  Msg := E.Message; // or E.ToString
  Application.MessageBox(PChar(Msg), PChar(Application.Title), MB_OK + MB_ICONSTOP);
end;
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.160 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: Warum zeigt Application.ShowException(..) die INNERSTE?

  Alt 24. Aug 2015, 11:57
Danke für die seelische Bestätigung. Wenn man sich nicht alleine wundert, wundert man sich gleich viel weniger.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 07:42 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