Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben? (https://www.delphipraxis.net/88674-bei-try-except-zeilenr-der-fehlerhaften-zeile-ausgeben.html)

KoS 19. Mär 2007 09:59


Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben?
 
Hallo zusammen,

ist es möglich bei einem try..except die Zeilennummer der "fehlerhafte" Zeile im Source auszugeben?
Bei mir ist es so das ich Logdateien schreibe und ich mehrere potentielle Fehler innerhalb eines try-blocks abhandel und diese nicht alle in einzelne try..except Blöcke verpacke. Nun stellt sich mir eben die Frage wenn ein Fehler auftraucht, in welcher Zeile im Quellcode der Fehler aufgetreten ist, da unter anderem die selben Funktionen mehrfach an verschiedenen Stellen im Code vorkommen.

Manch einer kennt das ja aus manchen Anwendungen wo dann so schöne Fehler kommen wie "Fehler in Zeile X (blabla.c)" oder sowas.

Vielen Dank!

Gruß KoS

turboPASCAL 19. Mär 2007 10:06

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Nein. In der Exec gibts ja dann och keine Zeihlennummer nicht. :mrgreen:
Du kannst doch aber den Procedurennamen in die Log schreiben.

Luckie 19. Mär 2007 10:09

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Guck mal, ob du mit Delphi-Referenz durchsuchenAssert weiter kommst.

KoS 19. Mär 2007 10:12

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Zitat:

Zitat von turboPASCAL
Nein. In der Exec gibts ja dann och keine Zeihlennummer nicht. :mrgreen:
Du kannst doch aber den Procedurennamen in die Log schreiben.

Der Prozedurname ist ja bereits drin, aber glaubst du das ich dann bei über 250 Zeilen weiß welche von den verschiedenen z.b. StrToFloat Funktionen probleme bei der Umwandlung macht?
Und ich möchte vermeiden um jede einzelne ein try..except zu machen.

turboPASCAL 19. Mär 2007 10:14

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Zitat:

Zitat von turboPASCAL
Nein. In der Exec gibts ja dann och keine Zeihlennummer nicht. :mrgreen:
Du kannst doch aber den Procedurennamen in die Log schreiben.

// Edit:

Du kannst aber, so mach ich es, im QuellCode mit Hints arbeiten (ab D5). Diese kann man dann Loggen
und im Quelltext leichter finden.

Delphi-Quellcode:
{$MESSAGE Hint '*** Procedure DecodeString...'}
procedure DecodeString(_In, _Out: Pointer);
begin
  try
    //...
  exept
    //...
    WriteLogFile('Procedure DecodeString Error', TimeToStr(Now));
  end;
end;
// Edit II:

Ohhh, :gruebel: habe wohl den Quote Button erwischt... -.-"

himitsu 19. Mär 2007 10:16

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Delphi-Referenz durchsuchenExceptAddr liefert wohl erstmal die Stelle in der Exe

und dann gab's da noch irgendwas, welches diese Position "umrechnen" konnte.

KoS 19. Mär 2007 10:20

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Zitat:

Zitat von Luckie
Guck mal, ob du mit Delphi-Referenz durchsuchenAssert weiter kommst.

Sieht eigentlich garnicht so schlecht aus, aber irgendwie versteh ich noch nicht so ganz wie ich das einsetzten soll. Kannst du mir da ein Beispiel für z.B. StrToFloat(s) geben?

@turboPASCAL: so ähnlich mache ich es ja bereits, nur micht mit diesem {$MESSAGE}, ich schreib einfach am anfang meiner Procedure eine begin text mit dem Namen der Prozedur und am ende auch, mittendrin dann ggf. noch weitere Infos was passiert oder eben beim Except noch die Exception.Message meldung.

Zitat:

Zitat von himitsu
Delphi-Referenz durchsuchenExceptAddr liefert wohl erstmal die Stelle in der Exe

und dann gab's da noch irgendwas, welches diese Position "umrechnen" konnte.

Hmm ... das mit dem "umrechnen" in die Zeilen wäre natürlich noch ne Voraussetzung, sonst könnte ich damit nicht all zu viel anfangen. (ganz so bewandert bin ich leider nicht in Delphi)

himitsu 19. Mär 2007 10:24

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Na ja, ich auch nicht so, aber es gibt so Projekte wo die ganzen Debuginformationen mit in der Exe gepeichert werden und dann darüber die Zeile zur Position bestimmt werden kann.

und sowas?
Delphi-Quellcode:
Var LastPos: Integer;


LastPos := 0;
Try
  Befehl1;
  LastPos := 1;
  Befehl2;
  LastPos := 2;
  Befehl3;
  LastPos := 3;
  Befehl4;
  ...

Except
  Case LastPos of
    0: Fehler bei Befehl 1
    1: Fehler bei Befehl 2
    2: Fehler bei Befehl 3
    3: Fehler bei Befehl 4 
    ...
  End;
End;

KoS 19. Mär 2007 10:26

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Hm das wäre fast genau so aufwendig als überall ein try drum zu machen.
Ich versuch das Programm ja nach möglichkeit nicht unnötig mit solchen Zeilen aufzublähen.

himitsu 19. Mär 2007 10:47

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
hier ohne sich verscheiben/zählen zu können ... jedenfalls nich bei der Programmierung, da dort nur Copy&Paste.
Delphi-Quellcode:
LastPos := 0;
Try
  Befehl1;
  Inc(LastPos);
  Befehl2;
  Inc(LastPos);
  Befehl3;
  ...

Except
  Fehler bei Befehl (LastPos)
End;

OldGrumpy 19. Mär 2007 10:52

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Schau Dir mal MadExcept von Madshi an, das dürfte Dir alles liefern was Du willst. Das Lizenzmodell ist auch sehr erträglich, und vor allem ist das ganze wirklich bequem in der Anwendung ohne grossartig Code zu schreiben.

IngoD7 19. Mär 2007 10:55

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Zitat:

Zitat von KoS
(...) aber glaubst du das ich dann bei über 250 Zeilen weiß welche von den verschiedenen z.b. StrToFloat Funktionen probleme bei der Umwandlung macht?
Und ich möchte vermeiden um jede einzelne ein try..except zu machen.

Wie wäre es denn mit Fehlervermeidung? ;)
Oder anders herum: Welche Fehlerfälle könnten denn passieren, die du nicht vorher abfangen könntest, bevor du den String umzuwandeln versuchst?

Es hat fast den Anschein, als würdest du Exceptions als "Stilmittel" zur Gültigkeitsüberprüfung verwenden, anstatt folgendes zu tun:
Delphi-Quellcode:
if StringIstSauber(StringA) then
   FloatB := StrToFloat(StringA)
else
   SchreibeProtokoll('ProtEintrag');
:gruebel:

Muetze1 19. Mär 2007 11:07

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Mit ExceptAddr und einem MAP Datei kann man höchstens die Methode/Procedure ermitteln, aber nicht die Zeilennummer. Diese kann man damit nicht ermitteln. Von daher bringt dich das nicht weiter.

sakura 19. Mär 2007 11:12

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Zitat:

Zitat von turboPASCAL
Nein. In der Exec gibts ja dann och keine Zeihlennummer nicht.

Doch, ist gar kein größeres Problem. Suche mal nach Hier im Forum suchenmadExcept - da gibt es hier auch ein Tutorial.

...:cat:....

P.S.: Ich sehe gerade OldGrumpy hat es auch schon empfohlen :oops: Aber es ist wirklich gut und ich nutze es in unserer Haussoftware ebenfalls.

SirThornberry 19. Mär 2007 11:20

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
MadExcept nutzt vermutlich auch nur die DebugInfos. Es wäre interessant wie man diese auslesen kann bzw. wie diese aufgebaut sind.

sakura 19. Mär 2007 11:23

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Zitat:

Zitat von SirThornberry
MadExcept nutzt vermutlich auch nur die DebugInfos. Es wäre interessant wie man diese auslesen kann bzw. wie diese aufgebaut sind.

Tut es, ja. Wenn ich mich recht entsinne, dann habe ich für 4 Jahren oder so hier mal Source Code dafür gepostet...

...:cat:...

KoS 19. Mär 2007 11:31

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Ich hab mir das madExcept mal auf der Homepage angeschaut, aber kann das Teil auch im Hintergrund aggieren, ohne sichtbare Fenster aufzurufen?

Es handelt sich bei mir nämlich um einen Windows-Dienst, der natürlich keine Fenster öffnen soll.

@IngoD7: Natürlich versuche ich vorher einige Fehler vorweg zu nehmen, nur leider gelingt das nicht immer so wie es soll, da es sich nicht direkt um statische Quellen Handelt. Genau genommen werden die Daten von einer Webseite bezogen und der HTML-Code wird aus irgendwelchen bisher noch nicht auffindbaren Gründen teilweise falsch übermittelt, bzw. falsch vom Programm verarbeitet. (ich würde mal 15-30% Fehlerquote schätzen, genau kann ich das nicht sagen)

Was mir erst aufgefallen ist:
'309.29' is not a valid floating point value
Irgendwie finde ich das komisch, Float arbeitet doch mit . und das klappt an allen möglichen Stellen und ich prüfe auch mit einer Routine ob es sich um ein Float handelt, aber in diesem Fall schlägt das StrToFloat immer fehl.

mkinzler 19. Mär 2007 11:35

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Zitat:

309.29' is not a valid floating point value
Irgendwie finde ich das komisch, Float arbeitet doch mit . und das klappt an allen möglichen Stellen und ich prüfe auch mit einer Routine ob es sich um ein Float handelt, aber in diesem Fall schlägt das StrToFloat immer fehl.
StrToFloat verwendet die Systemeinstelleung für den dezimalTrenner (DecimalSeparator) bzw Tausendertrenne ( ThousandSeparator), welche bei einem deutschen Windows ',' und '.' sind.

KoS 19. Mär 2007 11:50

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Zitat:

Zitat von mkinzler
StrToFloat verwendet die Systemeinstelleung für den dezimalTrenner (DecimalSeparator) bzw Tausendertrenne ( ThousandSeparator), welche bei einem deutschen Windows ',' und '.' sind.

Hmm, ich war bisher immer der Meinung das klappt mit dem Punkt, das kann aber sein das die Werte alle keine Nachkommastelle hatten.
Kann man das irgendwo festlegen ob Punkt oder Komma verwendet werden soll? Wenn das Programm auf einem englischem System läuft würde ja dann wieder ne Exception kommen.

IngoD7 19. Mär 2007 11:51

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Zitat:

Zitat von KoS
@IngoD7: (...)und der HTML-Code wird aus irgendwelchen bisher noch nicht auffindbaren Gründen teilweise falsch übermittelt, bzw. falsch vom Programm verarbeitet.

Eher letzteres, oder? :zwinker: Und genau daran gilt es, zu arbeiten. :)

Zitat:

Zitat von KoS
'309.29' is not a valid floating point value
Irgendwie finde ich das komisch, Float arbeitet doch mit . und das klappt an allen möglichen Stellen und ich prüfe auch mit einer Routine ob es sich um ein Float handelt, aber in diesem Fall schlägt das StrToFloat immer fehl.

Siehste, da geht's schon los. "." durch "," ersetzen und die Welt sieht schon gleich viel rosiger aus. :)

Das ist das, was ich grundsätzlich meinte: Exceptions sind (nach meiner bescheidenen Meinung) allermeistens das Ende eines (programmtechnischen) "Missverständisses". Sobald eine geworfen wird, gucken warum und Missverständnis aus dem Weg räumen. Ganz besonders bei häufigen Exceptions. Solange Exceptions die Regel und nicht die Exception (=Ausnahme :zwinker: ) sind, hat der Programmierer noch andere Dinge zu tun, als sich über viele oder weniger viele try..except-Blöcke Gedanken zu machen. :)

mkinzler 19. Mär 2007 11:53

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Zitat:

Kann man das irgendwo festlegen ob Punkt oder Komma verwendet werden soll?
Ja durch setzen der Konstanten DecimalSeparator bzw ThousandSeparator oder durch Verwendung der Funktion überladenen StrToFloat-Funktion

himitsu 19. Mär 2007 12:04

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Zitat:

Zitat von KoS
Hmm, ich war bisher immer der Meinung das klappt mit dem Punkt, das kann aber sein das die Werte alle keine Nachkommastelle hatten.

Delphi ignoriert praktischer Weise die lokalen Einstellungen.
Im QuellCode ist "." der Dezimaltrenner.
(wäre och blög, wenn der Deutsche keine englischen Progamme kompilieren könnte :stupid: )

Zitat:

Zitat von KoS
Kann man das irgendwo festlegen ob Punkt oder Komma verwendet werden soll? Wenn das Programm auf einem englischem System läuft würde ja dann wieder ne Exception kommen.

Ja, die Einstellungen werden beim Programmstart ausgelesen und dann lokal in den entspechenden Variablen abgespeichet, welche du natürlich auch selber ändern/setzen kannst.

siehe Delphi-Referenz durchsuchenDecimalSeparator und Tausendertrenne, oder eben die passende Delphi-Referenz durchsuchenStrToFloat

KoS 19. Mär 2007 12:31

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Das weicht jedoch alles vom eigentlichen Thema ab.

@IngoD7: Es ist ja nicht so das ich nur auf Grund dieses Fehlers ein Exception bekomme. Das war halt jetzt 1 Fehler der mir aufgefallen ist und wo ich vielleicht von der Programmierung her etwas unwissentlich gehandelt habe. Zumal eben Delphi intern mit '.' rechnet.

Muetze1 19. Mär 2007 12:40

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Um das angesprochene Problem zu beheben, nutze ich immer einen solchen (oder ähnlich gelagerten) Code:

Delphi-Quellcode:
Function MyStrToFloat(AString: String): Float;
Begin
  AString := StringReplace(AString, '.', DecimalSeparator, []);
  AString := StringReplace(AString, ',', DecimalSeparator, []);
  Result := StrToFloat(AString);
End;

shmia 19. Mär 2007 13:00

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Delphi erzeugt ja gerne mal Exceptions, die so allgemein sind, dass der Benutzer nichts damit anfangen kann. (z.B. "ungültige Variantumwandlung")
Hier muss man als Programmierer mitdenken und an strategisch günstigen Stellen die Exception abfangen, erweitern und neu auslösen:
Delphi-Quellcode:
procedure TForm1.ButtonImport(Sender:TObject);
begin
   if FileDialog1.Execute then
   begin
      try
         ImportXMLfile(FileDialog1.Filename);
      except
         on E:Exception do
         begin
            // sinn- und gehaltvolle Fehlermeldung bilden
            E.Message := 'XML - Import'#13#10+
               'Fehler beim Importieren der Datei <'+FileDialog1.Filename+'>'#13#10+
               E.Message; // auf jeden Fall die orginale Meldung anhängen !!
            Raise; // Exception erneut auslösen
         end;
      end;
   end;
end;
Man hütte sich davor, anstelle von Raise etwa ShowMessage zu verwenden. :warn:
Mit dieser Technik kann man Programme schreiben, die jederzeit präzise Fehlermeldungen ausgeben,
mit denen sowohl der Benutzer, als auch der Programmierer etwas anfangen kann.

Sinnvoll lässt sich diese Technik auch innerhalb von Schleifen einsetzen:
Delphi-Quellcode:
for i := 0 to stringlist.Count-1 do
begin
   try
     ImportCSVdaten(stringlist[i]);
   except
      on E:Exception do
      begin
         E.Message := Format('Fehler in Zeile %d'#13#10, [i])+
            E.Message;
         raise;
      end;
   end;
end;

LAWn-M0W3R 19. Mär 2007 14:16

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Tach,
um mal wieder auf das Anfangsthema zurückzukommen:
Delphi-Quellcode:
try
 //fehlerhafter Quelltext
except
 Assert(false,'Fehler SoUndSo');
end;
Die Fehlerausgabe sieht dann ungefähr so aus:
Zitat:

Fehler SoUndSo (D:\new\Unit1.pas, Zeile 34)
Achtung: Nicht wundern, in Delphi werden natürlich die normalen Compiler-Fehler ausgegeben, aber wenn du dann die kompilierte EXE unabhängig von Delphi startest, dann bekommst du deine Exception wie oben angegeben!

Grüße
der MAX

KoS 19. Mär 2007 15:40

Re: Bei try..except Zeilenr. der fehlerhaften Zeile ausgeben
 
Kann man das Assert() auch in die Logfile bzw. in ne String-Variable lenken?
Da es ja ein Dienst ist sollte es nicht als MsgBox oder derartiges kommen.

Als ich mit dem Assert mal kurz gespielt hab ist mir aufgefallen, das immer genau die Zeile ausgegeben wird in der das Assert(false) ist. Irgendwie bringt mich das dann im Except auch nicht weiter weil ich ja anfänglich sagte, das der try-Block recht groß ist und ich ja die Zeile von dem Fehler und nicht von dem Exception brauche.

Bleibt mir wohl wirklich nix anderes übrig als nach eine der Bereits genannten Lösungen vorzugehen?


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