Delphi-PRAXiS
Seite 2 von 4     12 34      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Die Delphi-IDE (https://www.delphipraxis.net/62-die-delphi-ide/)
-   -   Zur Laufzeit, Zeilennummer feststellen (https://www.delphipraxis.net/196005-zur-laufzeit-zeilennummer-feststellen.html)

Delphi.Narium 16. Apr 2018 12:56

AW: Zur Laufzeit, Zeilennummer feststellen
 
Programm mit ausführlicher MAP-Datei kompilieren.

Fehleradresse in dieser suchen.

Vor der Fehleradresse steht die Zeilennummer.

Die erste Zeile mit einer Quelltextangabe (Line numbers for ...), vor der gefundenen Fehleradresse, gibt die Quelltextdatei an, in welcher der Fehler auftrat.

Damit hat man dann die Quelltextdatei, Fehleradresse und die Zeilennummer des fehlerverursachenden Quelltextes. Die Fehlermeldung entnimmt man direkt der Exception.

Das sollte mit wenig Aufwand in 'nem halben Arbeitstag umzusetzen sein. Und wenn man schon ein eigenes Fehlerhandling hat, kann man das entsprechend um eine Methode erweitern, die die Fehleradresse annimmt, die MAP-Datei entsprechend durchsucht und als Ergebnis den Namen der Quelltextdatei, zuzüglich der Zeilennummer, liefert.

Es sind prinzipiell alle Informationen bereits vorhanden, man muss sie nur nutzen.

günni0 16. Apr 2018 13:13

AW: Zur Laufzeit, Zeilennummer feststellen
 
Wenn ihr JCL nutzt, kann das hier helfen.
Das Projekt wird im Debug-Modus etwa 100 KB größer. Im Release bei mir 140 KB. Also nicht die Welt.


https://stackoverflow.com/questions/...w-an-exception

KodeZwerg 16. Apr 2018 20:14

AW: Zur Laufzeit, Zeilennummer feststellen
 
Aber Zeilennummern aus einer Objekt orientierten Programmiersprache heraus zu holen ist doch eh ein falscher Ansatz.
Beispiel Procedure X ruft Function Y auf die wiederum einen externen Call Z macht, welche Zeilennummer soll angezeigt werden bei Fehler?
Das was in X falsch war oder in Y oder gar Z ??? Ich hoffe das ich meine Sicht verständlich darlege.
Besser bei Klassennamen und deren Message bleiben, da sollte dann sofort klar sein wo & warum Fehler YXZ entstand.
Alternativ kannst Du Dir ja einen Globalen Counter reinbauen und dem bei jeder Neuen Code Zeile dessen Zeilennummer voranstellen, noch primitiver gehts kaum aber Du bist am Ziel.
Beispiel
Delphi-Quellcode:
0 - var Zeile : Cardinal;
1 - procedure x;
2 - begin
3 -  Zeile := 3; MachWas;
4 -  Zeile := 4; MachMehr;
5 - end;

FaTaLGuiLLoTiNe 17. Apr 2018 10:13

AW: Zur Laufzeit, Zeilennummer feststellen
 
Wirklich aussagekräftig für den Entwickler ist eigentlich nur die Kombination aus Fehlerklasse, Fehlermeldung und Callstack. Das wäre schon mal eine gute Momentaufnahme der Situation, die man auch im Debugger sehen könnte, wenn der Fehler dort auftreten würde.

Das einzige was dann noch fehlt, wäre der Zustand des Programms zum Fehlerzeitpunkt (also die Variableninhalte), aber das würde wohl eindeutig den Rahmen jedweder Fehlermeldung oder Logdatei sprengen.

jus 17. Apr 2018 15:01

AW: Zur Laufzeit, Zeilennummer feststellen
 
Hallo,

ich verwende zum Ermitteln der Zeilennummer die JCL, da ich in meinem Programmen häufig Fehler in eine Logdatei reinschreibe, der coole Tipp kam von diesem Forum hier. Der Vorteil ist, dass JCL eigentlich nicht wirklich was kostet.
Meine Logfunktion schaut in etwa so aus:
Delphi-Quellcode:
implementation
uses JCLDebug;

procedure Log(S: String);
var
  msg: String;
  Year, Month, Day, Hour, Min, Sec, MSec, H: Word;
begin
  DecodeTime(now, Hour, Min, Sec, MSec);
  msg := Format('%.2d:%.2d:%.2d.%.3d %s:%u (%s) "%s"',[Hour,Min,Sec,MSec,FileByLevel(1), LineByLevel(1), ProcByLevel(1), S]);

  // hier schreibe ich die Fehlermeldung in eine Datei oder lasse es im Programm ausgeben
  //......
end;
Meine Logdatei schaut dann so aus, wobei nach dem Unitnamen die Zeilennummer ist.
Code:
23:03:53.262 Unit1.pas:2787 (TForm1.Update_CmB_Printer) "Fehler! Der Druckername "TM88IV" konnte nicht unter den installierten Druckern gefunden werden."
23:03:53.264 Unit1.pas:2794 (TForm1.Update_CmB_Printer) "Der aktive Druckername wird auf "TMU290" gesetzt."
23:03:53.266 Unit1.pas:536 (TForm1.FillPrinterDataToGui) "Current printer model "TM88IV" match with "C:\ProgramData\XXX\XXX\PrinterInfo.xml"
23:03:53.268 PrinterLib.pas:1104 (PrinterXmlGetStandardFeedsources) "In C:\ProgramData\XXX\XXX\PrinterInfo.xml <feedsource name="01"> node no <borderless> found."
23:03:53.270 Unit1.pas:550 (TForm1.FillPrinterDataToGui) "C:\Users\abc\AppData\Roaming\XXX\MediaNotVisible found"
23:03:53.272 Unit1.pas:1172 (TForm1.LoadPresets) "---TForm1.LoadPresets---"
23:03:53.273 Unit1.pas:1173 (TForm1.LoadPresets) "TForm1.LoadPresets: Suche alle Presets in C:\Users\abc\AppData\Roaming\XXX\PRESET\*.epl mit dem Druckermodel TM88IV"
23:03:53.282 Unit1.pas:1231 (TForm1.LoadPresets) "INVALID: C:\Users\abc\AppData\Roaming\XXX\PRESET\14_20150730_190038.epl"
Die JCL Debugfunktionenn können natürlich viel mehr wie z.B. Stacktrace ausgeben usw. siehe den alten Beitrag hier.

Lg,
jus

günni0 17. Apr 2018 15:01

AW: Zur Laufzeit, Zeilennummer feststellen
 
Zitat:

Der Vorteil ist, dass JCL eigentlich nicht wirklich was kostet.
Bis auf einen kleinen Hinweis im Programm, dass es JCL verwendet, sollte es nichts kosten :P

Könntest du eventuell ProcByLevel erklären?

Wenn Prozedur A einen Fehler hat und Prozedur B_Log aufruft und letztere wieder ProcByLevel(0), dann habe ich im Log den Namen B_log stehen.
Heißt ProcByLevel(1) nur "gehe eine Prozedur weiter zurück? Wenn ja, was, wenn ich X Prozeduren habe die sich hintereinander aufrufen?

himitsu 17. Apr 2018 15:11

AW: Zur Laufzeit, Zeilennummer feststellen
 
Zitat:

Heißt ProcByLevel(1) nur "gehe eine Prozedur weiter zurück?
Ja, aber du solltest das Programm mit Stack-Frames kompileren, denn sonst erkennt der Stacktrace kleinere Funktionen garnicht.

günni0 17. Apr 2018 15:12

AW: Zur Laufzeit, Zeilennummer feststellen
 
Hat das irgendwelche Nachteile bezüglich der Sicherheit des fertigen Kompilats?

FileByLevel, LineByLevel, ProcByLevel. Was aber wenn ich nicht wie weit ich zurück muss? Ist mir mir gerade nicht so, aber für die Zukunft wäre das interessant.

Hier nur ein Beispiel.
In meiner Mainform ist eine Prozedur AppExceptionHandler.
Die ruft eine Prozedur doLog in einer Log-Unit auf und doLog ruft letzten Endes die Prozedur auf, die das Log schreibt.
Gehe ich 3x zurück, lande ich bei Vcl.Forms.pas.

himitsu 17. Apr 2018 15:23

AW: Zur Laufzeit, Zeilennummer feststellen
 
Zitat:

Zitat von günni0 (Beitrag 1399572)
Was aber wenn ich nicht wie weit ich zurück muss?

Sowas hab ich grade in Postgres bei einer Funktion eingebaut, im Grunde mit einer Blacklist.

Die Funktion wird auch von Anderen aufgerufen, wobei Einige dafür auch nur interne Loggingfunktionen sind.
Ich gehe den Stacktrace nun einfach so lange rückwärts, bis ich einen "mir unbekannten" Funktionsnamen finde und dieser kommt ins Log.

günni0 17. Apr 2018 15:34

AW: Zur Laufzeit, Zeilennummer feststellen
 
Gerade mal mit einer Schleife und ProcByLevel nachgebaut.


Zitat:

TLogFunctions.doExceptionLog
Form.Main.TForm1.AppExceptionHandler
Forms.TApplication.HandleException
Classes.StdWndProc$qqsp6HWND__uiuiui
FileByLevel dementsprechend
Zitat:

uLog.pas
<projektname>.Form.Main.pas
Vcl.Forms.pas
System.Classes.pas
Danach kommt nix mehr. Darf man bei sowas keinen eigenen HandleException haben?


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:10 Uhr.
Seite 2 von 4     12 34      

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