![]() |
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. |
AW: Allgemein: Wie findet man einen Fehler?
Hallo,
installiere MadExcept. Heiko |
AW: Allgemein: Wie findet man einen Fehler?
irre, was es so alles gibt.
Danke für den Tip, werde ich gleich mal ausprobieren :) |
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. |
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? |
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:
Deine Methoden prüfen als allererstes, ob die übergebenen Parameter gültig sind.
myObject := FindMyObject(someSearchCriteria);
if not Assiged(myObject) then raise Exception.Create('myObject is not set');
Delphi-Quellcode:
Dafür gibt es zudem die 'Assert' ('Stelle sicher das...') Methode...
Procedure TMyClass.SomeObject (someParameter : TParameter);
Begin if not Assiged(someParameter ) then raise Exception.Create('someParameter is not set'); ...
Delphi-Quellcode:
Dann schalte noch die Bereichsprüfung an (Compiler-Optionen), um sicherzugehen, das Du immer auf gültige Arrayelemente zugreifst.
myObject := FindMyObject(someSearchCriteria);
Assert (Assiged(myObject),'myObject is not set'); ... Procedure TMyClass.SomeObject (someParameter : TParameter); Begin Assert (Assiged(someParameter), 'someParameter is not set.'); ... 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. |
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 |
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:
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?
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; |
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:
sl.Strings[z]; und inc(z); Wie stellst du denn sicher, dass z nie grösser wird als die Stringlist? Gruß Dirk |
AW: Allgemein: Wie findet man einen Fehler?
Zitat:
Zitat:
Delphi-Quellcode:
.
raise Exception.Create('Mein Test-Fehler');
|
AW: Allgemein: Wie findet man einen Fehler?
Zitat:
Delphi-Quellcode:
Es knallt an einer definierten Stelle und nicht 'irgendwo'. Obwohl das 'irgendwo' nun gerade die nächste Zeile ist, insofern... Ist das weniger FailFast und eher 'debug-code'. Aber im ein "Assert" ist es... ;-)
procedure TForm1.TimerEventExecute(Sender: TObject);
begin Assert((z>=0) and (z<sl.count),'z ist zu klein oder größer als die Länge von sl'); // <<<<< chrd := sl.Strings[z]; If chrd <> '' then PlaySound(PChar(chrd), hInstance, snd_ASync or snd_Resource); inc(z); end; |
AW: Allgemein: Wie findet man einen Fehler?
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
|
AW: Allgemein: Wie findet man einen Fehler?
Hi,
Zitat:
|
AW: Allgemein: Wie findet man einen Fehler?
Vielleicht solltest Du den Quellcode noch anhängen.
|
AW: Allgemein: Wie findet man einen Fehler?
Zitat:
das
Delphi-Quellcode:
ist u.U. auch ein guter Ort dafür oder
end.
Delphi-Quellcode:
.
finalization
Gruß K-H |
AW: Allgemein: Wie findet man einen Fehler?
Zitat:
Debuggen ist Übung und man muss ein Gefühl dafür entwickeln. Mit der Zeit (Erfahrung und Wissen) kennt man übliche Fehlerquellen oder weis auch selbst bei welcher Code Stelle man sich unsicher gefühlt hat beim schreiben. Im Notfall setzt du den Haltepunkt ganz am Anfang und gehst Schritt für Schritt durch, das klingt anfangs etwas viel aber normal sollte dein Programm ja keine Tausendzeilen Code durchlaufen wenn du nur mal einen Testfall prüfst. |
AW: Allgemein: Wie findet man einen Fehler?
Hallo zusammen,
einen Riesenfehler hast Du schon einmal, wenn Du nach dem Programmstart, ohne dass Du ein "Lied" selektiert hast, auf "Pause" drückst und dannach sofort aus "Cont". Hier würde ich einmal ansetzten zu suchen. "Keine Daten da, aber weitermachen" kann nicht gutgehen. Und heisst Deine "Form1" auch tatsächlich immer "Form1"?
Delphi-Quellcode:
procedure TimeCallBack(TimerID, Msg: Uint; dwUser, dw1, dw2: DWORD); pascal;
begin With Form1 do begin TimerEvent.Execute; end; end; Edit: Das Teil steckt ja voller Fehler. Wenn man wärend des Abspielens die Clear-Taste drückt, dann kommt eine Exception. Hast Du ein paar Akkorde eingegeben und spielst diese komplett ab und löscht dann das Memo-Feld, dann wird nur das Memo gelöscht, aber die Akkorde sind weiter da und können abgespielt werden. |
AW: Allgemein: Wie findet man einen Fehler?
Die im ersten Post gezeigte CPU Ansicht lässt auf jeden Fall darauf schließen, dass versucht wird die virtuelle Methode eines nicht erzeugten Objekts zu callen. Das MOV EAX, [EAX] ist vermutlich die Dereferenzierung des Objekts mit dem Ziel die Adresse der VTable zu ermitteln. Da hagelt es dann die Exception, da EAX (das Objekt) in deinem Context noch nicht created wurde.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:13 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz