Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Allgemein: Wie findet man einen Fehler? (https://www.delphipraxis.net/183112-allgemein-wie-findet-man-einen-fehler.html)

nezumi7 12. Dez 2014 08:01

Allgemein: Wie findet man einen Fehler?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Liebe Alle,

ich schreibe gerade ein Prog (Delphi 6), das mir beim Gitarre-lernen helfen soll (man gibt Akkorde in ein RichEdit ein und die werden dann aus einer Resource geladen und abgespielt). Funktioniert alles super, wegen der vielen Einstellungsmöglichkeiten (Takt, Auf- / Abschläge, Wiederholungen, Geschwindigkeit etc.) ist das Programm ziemlich umfangreich geworden.

Leider tritt immer wieder ein Fehler auf, allerdings sehr selten und ohne erkennbaren Anlass, so dass es mir kaum möglich ist, den irgendwie zu reproduzieren. Von der Fehlermeldung habe ich den angehängten Screenshot gemacht. Für mich ist das völlig unverständlich.

Kann man da irgendeine Information rausziehen, die einem bei der Fehlersuche helfen könnte oder wie geht man da am besten vor?

(der Quellcode ist ein paar tausend Zeilen lang, so dass ich mal davon absehe, ihn hier zu posten).

Greetings,
Stephan.

hoika 12. Dez 2014 08:11

AW: Allgemein: Wie findet man einen Fehler?
 
Hallo,

installiere MadExcept.


Heiko

nezumi7 12. Dez 2014 08:17

AW: Allgemein: Wie findet man einen Fehler?
 
irre, was es so alles gibt.

Danke für den Tip, werde ich gleich mal ausprobieren :)

himitsu 12. Dez 2014 09:03

AW: Allgemein: Wie findet man einen Fehler?
 
Aus der CPU-Ansicht kann man selten die fehlerverursachende Stelle erkennen.
Wichtiger wäre hier ein Blick in den Stacktrace (Ansicht > Debug-Fenser > Aufruf-Stack), denn da sieht man nicht nur die aktuelle Stelle (wo es nach dem Knall hängen blieb), sondern auch wo der Aufruf her kann. (mit etwas Glück auch die Stelle, deines Codes, welche zuletzt ausgeführt wurde)

Wenn es im laufenden Betrieb auftritt, ohne daß man einen Debugger dran hat, dann kann man sich mit dem Debugger auch naträglich verbinden und schauen wo es hängt.
Den Fehlerdialog nicht wegmachen > Delphi staten > Start > Mit Prozess verbinden > uns los geht es.
(bei Erekalog geht das nicht, da dieses Mistding den Fehlerthread weiterlaufen lässt und den Fehlerdialog in einem anderen Thrad anzeigt ... oder irgendwie sowas, aber zum Glück zeigen die einen eigenen Stacktrace an, womit nicht gleich alles verloren ist)

Neben MadExcept gibt es auch noch EurekaLog uvm.

nezumi7 12. Dez 2014 09:12

AW: Allgemein: Wie findet man einen Fehler?
 
Danke himitsu,

da ich bei madexcept noch nicht so richtig durchsteige, werde ich auch Deine Tips versuchen.

Letztlich muss ich aber bei allen Varianten warten, bis der Fehler mal wieder auftritt, oder?

Dejan Vu 12. Dez 2014 09:13

AW: Allgemein: Wie findet man einen Fehler?
 
Ich würde deinen Code mit Fail fast - Anweisungen spicken. Die tun nicht weh (im Gegenteil) und machen die Anwendung i.A. auch nicht langsamer.

Fail fast bedeutet: Wenn Du irgend etwas suchst, ermittelst oder berechnest, fragst Du sofort danach ('fast') ab, ob das Ergebnis im Rahmen dessen ist, was Du erwartest. Wenn nicht, sofort mit einer Exception abbrechen ('fail').

Delphi-Quellcode:
myObject := FindMyObject(someSearchCriteria);
if not Assiged(myObject) then raise Exception.Create('myObject is not set');
Deine Methoden prüfen als allererstes, ob die übergebenen Parameter gültig sind.
Delphi-Quellcode:
Procedure TMyClass.SomeObject (someParameter : TParameter);
Begin
  if not Assiged(someParameter ) then raise Exception.Create('someParameter is not set');
  ...
Dafür gibt es zudem die 'Assert' ('Stelle sicher das...') Methode...
Delphi-Quellcode:
myObject := FindMyObject(someSearchCriteria);
Assert (Assiged(myObject),'myObject is not set');
...
Procedure TMyClass.SomeObject (someParameter : TParameter);
Begin
  Assert (Assiged(someParameter), 'someParameter is not set.');
  ...
Dann schalte noch die Bereichsprüfung an (Compiler-Optionen), um sicherzugehen, das Du immer auf gültige Arrayelemente zugreifst.

Und zum Schluss: Beschäftige dich mit Unit-Tests. Klar, für ein Hobbyprojekt ein leichter Overkill, aber wenn man das mal gefressen hat, schreibt man einfach schneller richtig gut funktionierende Programme.

noisy_master 12. Dez 2014 09:20

AW: Allgemein: Wie findet man einen Fehler?
 
Hallo Gemeinde,

wo wir schon bei dem Thema sind hätte ich dazu auch noch eine Frage:

Bei mir ranzt mein Programm beim herunterfahren ab(genauen Fehler kann ich gerne bei Bedarf nachliefern). Ich habe Eurekalog laufen und bekomme auch einen wunderbaren callstack, ABER: es schein irgendwas mit irgendeinem Null-Pointer im Destruktor von einem TAdvEdit zu sein....und es tauchen nirgendwo meine Quellen in dem Stack auf...Was nun?
(ich glaube ich hatte sowas ähnliches schon mal war irgendwas mit nem TadvEdit auf nem Gridpanel
(bitte keine Kommentare zur Architektur :wink:) kann mich aber nicht mehr erinnern was das war bzw wie ich das gelöst habe)

Hat irgendwer ne Idee, wie ich dahinterkomme, welches meiner vielen AdvEdits da ein Problem hat?

Danke schon mal im voraus!

Gruß
Dirk

nezumi7 12. Dez 2014 09:39

AW: Allgemein: Wie findet man einen Fehler?
 
Danke Dejan Vu,

für einen Sonntag-Nachmittags Programmierer wie mich ist das starker Tobak, ich würde es aber trotzdem gerne mal so versuchen, weiß aber nicht so recht wie.

Ich glaube, dass der Fehler bei meinem Timer liegt und poste mal den extrem gekürzten Code hierzu

Delphi-Quellcode:
procedure TimeCallBack(TimerID, Msg: Uint; dwUser, dw1, dw2: DWORD); pascal;
begin
With Form1 do begin
TimerEvent.Execute;
end;
end;

procedure StartTimer(ms: Integer);
begin
 mmResult := TimeSetEvent(ms, 0, @TimeCallBack, 0, TIME_PERIODIC);
end;

procedure StopTimer;
begin
 TimeKillEvent(mmResult);
end;


procedure TForm1.startplayExecute(Sender: TObject);
begin
StartTimer(intervall);
end;


procedure TForm1.TimerEventExecute(Sender: TObject);
begin
chrd := sl.Strings[z];
If chrd <> '' then PlaySound(PChar(chrd), hInstance, snd_ASync or snd_Resource);
inc(z);
end;
Bitte nicht so kritisch anschauen, ich habs so stark gekürzt, dass es so nicht funktioniert, ich will nur das Prinzip verdeutlichen. Wie müsste ich da jetzt deine fail fast Abfrage einbauen?

noisy_master 12. Dez 2014 09:48

AW: Allgemein: Wie findet man einen Fehler?
 
Hi nezumi,


wie du da sinnvoll die Asserts einbaust weiss ich auch gerade nicht, aber wenn ich mir deinen Code so ansehe

Zitat:

Zitat von nezumi7 (Beitrag 1283203)
Danke Dejan Vu,
Delphi-Quellcode:
 
procedure TForm1.TimerEventExecute(Sender: TObject);
begin
chrd := sl.Strings[z];
If chrd <> '' then PlaySound(PChar(chrd), hInstance, snd_ASync or snd_Resource);
inc(z);
end;

dann sehe ich da sofort einen Kandidaten, der mir suspekt vorkommt:
sl.Strings[z]; und inc(z);

Wie stellst du denn sicher, dass z nie grösser wird als die Stringlist?

Gruß
Dirk

himitsu 12. Dez 2014 09:49

AW: Allgemein: Wie findet man einen Fehler?
 
Zitat:

Hat irgendwer ne Idee, wie ich dahinterkomme, welches meiner vielen AdvEdits da ein Problem hat?
Hast du mal versucht dein Programm schrittweise zu beenden? (Haltepunkt und dann F7)

Zitat:

Letztlich muss ich aber bei allen Varianten warten, bis der Fehler mal wieder auftritt, oder?
Ja, aber zum Probieren kannst du dir ja erstmal selber irgendwo einen Fehler erzeugen
Delphi-Quellcode:
raise Exception.Create('Mein Test-Fehler');
.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:01 Uhr.
Seite 1 von 2  1 2      

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