Programm steigt ohne ersichtlichen Grund aus

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Komoluna
Beiträge: 565
Registriert: So 26. Aug 2012, 09:03
OS, Lazarus, FPC: Windows(10), Linux(Arch)
CPU-Target: 64Bit

Programm steigt ohne ersichtlichen Grund aus

Beitrag von Komoluna »

Liebes Forum,

seit kurzen schreibe ich an einem kleinen Spiel, das an Pokémon angelehnt ist. Dies funktioniert soweit auch ganz gut, aber wenn man im Kampf eine Attacke auswählt, dann hängt sich das Programm auf.
Beim Schritt für Schritt Debugging sieht man, dass das Programm in Unit1.pas in Zeile 553 aussteigt

Code: Alles auswählen

 
    Repeat
      Case Key Of
        VK_W: m.Selected -= 1;
        VK_S: m.Selected += 1;
        VK_SPACE: Player.Battle.ClickSelectedItem;
      End;
      While m.Selected > Length(m.Items) - 1 Do    //<-- Hier in Zeile 553 steigt der Debugger ohne ersichtlichen Grund aus, und das Fenster reagiert nicht mehr...
        m.Selected := m.Selected - Length(m.Items);
      While m.Selected < 0 Do
        m.Selected := m.Selected + Length(m.Items);
    Until m.Items[m.Selected].Text <> '';  
Ich weiß, es ist viel Code, aber da ich absolut keine Ahnung habe, warum der Debugger einfach mitten im Quelltext aussteigt, ist es mit nicht gelungen, das Problem in einem Minimalbeispiel zu reproduzieren...

Die Attacke wird in GameClasses.pas in von Zeile 722 bis 735 ausgewählt. Dannach springt in Unit1.pas der Debugger in Zeile 553 einfach raus.
da ich weis, dass es schwierig ist, sich in fremden Code reinzufinden, beantworte ich gerne Fragen, um für mehr Verständnis zu sorgen...

Getestet und entwickelt unter:

Windows 7 (64bit)
Lazarus 1.0.14

P.S.: Um zu der problematischen stelle im code zu gelangen einfach mit "D" den spieler zu der figur rechts drehen und mit der Leertaste ansprechen, um Text zu bestätigen auch Leertaste benutzen, im Kampf mit WS durch das menü auf Kampf --> "Testattacke" oder "Testattacke 2.0" und dann mit Leertaste bestätigen...
Dateianhänge
Project1.rar
Der besagte Quellcode + Projektdateien...
(746.7 KiB) 98-mal heruntergeladen
Programmer: A device to convert coffee into software.

Rekursion: siehe Rekursion.

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Programm steigt ohne ersichtlichen Grund aus

Beitrag von Socke »

Warum versuchst du nicht die beiden While-Schleifen durch direkte Berechnungen zu ersetzen? Das wäre im Zweifelsfall sogar schneller.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: Programm steigt ohne ersichtlichen Grund aus

Beitrag von Scotty »

Auf D + Space passiert nichts (Schlimmes). Dafür crasht es beim Beenden in RenderBattle...
Unter Linux kann man uses <Windows> einfach löschen, und die Pfade müssen dort per Backslash getrennt werden, d.h. Maps\main.map (was auch unter Windows funktionieren sollte, ansonsten suchst du nach "DirectorySeparator").
Mir fällt aber auf, dass du die Debuginformationen entfernst (-Xs), dass du -O3 benutzt (AFAIK besser -O1 zum debuggen) und dass die Überprüfungen aus sind (-Ci,-Cr,-Ct,...). Vielleicht schaltest du einfach mal alles an und steppst dich nochmal durch den Code.

Komoluna
Beiträge: 565
Registriert: So 26. Aug 2012, 09:03
OS, Lazarus, FPC: Windows(10), Linux(Arch)
CPU-Target: 64Bit

Re: Programm steigt ohne ersichtlichen Grund aus

Beitrag von Komoluna »

ok, danke für die tipps, wer ich morgen nachmittag mal ausprobieren. ..
p.s. wie soll das mit den "direkten Berechnungen denn gehen, wenn ich zwischendrin noch auf tastatureingaben reagieren will? (ich hätte das gerne einfach in einer schleife, die den ganzen kampf berechnet...)

MFG Komoluna
Programmer: A device to convert coffee into software.

Rekursion: siehe Rekursion.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Programm steigt ohne ersichtlichen Grund aus

Beitrag von Michl »

Bekomme die Testattacke leider nicht hin :(

Dafür hat der Code bei mir zuerst gar nicht kompiliert (Argument can't be assigned to):

Code: Alles auswählen

Procedure TForm1.FormCreate(Sender: TObject);
...
  pkmn.Attacks[0].Name := 'Testattacke';  //<- hier meckert er 
Habe Code wie folgt ersetzt:

Code: Alles auswählen

Procedure TForm1.FormCreate(Sender: TObject);
Var
... 
  DAttacks: TAttacks;  //Variable-Dummy
begin
...
  DAttacks[0].Name := 'Testattacke';
  DAttacks[0].Damage := 10;
  DAttacks[1].Name := 'Testattacke 2.0';
  DAttacks[1].Damage := 20;
  DAttacks[2].Name := '';
  DAttacks[2].Damage := 0;
  DAttacks[3].Name := '';
  DAttacks[3].Damage := 0;
  pkmn.Attacks:=DAttacks;  
 
{  pkmn.Attacks[0].Name := 'Testattacke';
  pkmn.Attacks[1].Name := 'Testattacke 2.0';
  pkmn.Attacks[0].Damage := 10;
  pkmn.Attacks[1].Damage := 20;
}
  Map := TMap.Create;   
...
Dann startets Prog.
... einfach mit "D" den spieler zu der figur rechts drehen und mit der Leertaste ansprechen, um Text zu bestätigen auch Leertaste benutzen, im Kampf mit WS durch das menü auf Kampf --> "Testattacke" oder "Testattacke 2.0" und dann mit Leertaste bestätigen...
"D" gedrückt, Leertaste (Fenster öffnet sich "Lass uns kämpfen"), wieder Leertaste (Fenster verschwindet), W & S lässt Figur wieder laufen, nix Kampf :( (Lt. Debugger wird Player.fighting auch nicht auf true gesetzt, mehr habe ich jetzt nicht probiert)

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2822
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Programm steigt ohne ersichtlichen Grund aus

Beitrag von m.fuchs »

Was soll der Code denn bezwecken? Irgendwie scheint mir der Teil etwas unklar.
Alle Prüfungen einzuschalten ist auf alle Fälle eine gute Idee, da sind noch ein paar andere Kleinigkeiten die falsch laufen.

Und zu guter Letzt noch ein Hinweis: ein Self.DoubleBuffered := True; im OnFormCreate sorgt für flimmerfreie Bilder.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Komoluna
Beiträge: 565
Registriert: So 26. Aug 2012, 09:03
OS, Lazarus, FPC: Windows(10), Linux(Arch)
CPU-Target: 64Bit

Re: Programm steigt ohne ersichtlichen Grund aus

Beitrag von Komoluna »

was genau ist dir unklar?
welche prozedur,Unit, Zeile???
oder ein gesamter systemteil?
Programmer: A device to convert coffee into software.

Rekursion: siehe Rekursion.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2822
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Programm steigt ohne ersichtlichen Grund aus

Beitrag von m.fuchs »

Mir ist unklar, was die beiden While-Schleifen machen.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

martin_frb
Beiträge: 587
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: Programm steigt ohne ersichtlichen Grund aus

Beitrag von martin_frb »

Was fuer eine Meldung schreibt den der Debugger?

m ist ein Object. Ist das zugewiesen? Was zeigt Debug/Inspect oder Watches, oder Mouse hint?


---
Btw, wenn Length(m.Items) = 0 (empty / no items)
dann wird das ne lange schleife

Wenn der Debugger einfach nur nix meldet, mal pause drücken. Dann laueft das Programm (ggf endlos schleife)

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Programm steigt ohne ersichtlichen Grund aus

Beitrag von Michl »

Da hier niemand das Problem zu haben scheint, dass der Kampf aufgerufen wird, habe ich das Prog. nochmal unter Lazarus 1.0.14 gestartet und siehe da es funktioniert (unter 1.3 nicht!).
martin_frb hat geschrieben:Btw, wenn Length(m.Items) = 0 (empty / no items)
dann wird das ne lange schleife
Martin hatte den Finger drauf.

Falls Du mal eine Ausgabe der Werte mit einfügst z.B:

Code: Alles auswählen

...
      While m.Selected > Length(m.Items) - 1 Do begin//<<-- Hier Springt der Debugger heraus...
        writeln(IntToStr(Length(m.Items))+' - '+IntToStr(m.Selected)+' - '+IntToStr(Random(100))); //z.B. so
        m.Selected := m.Selected - Length(m.Items);
      end;
...
siehst Du das Problem.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Komoluna
Beiträge: 565
Registriert: So 26. Aug 2012, 09:03
OS, Lazarus, FPC: Windows(10), Linux(Arch)
CPU-Target: 64Bit

Re: Programm steigt ohne ersichtlichen Grund aus

Beitrag von Komoluna »

stimmt, die schleife würde bei einem leeren menü ewig weiterlaufen, aber warum sprint der Debugger dann einfach heraus?
(die schleifen sind dazu da, wenn man z.b. den letzten Menüpunkt ausgewählt hat, und dann "S" drückt, dann soll der erste Menüpunkt ausgewählt werden. )
Programmer: A device to convert coffee into software.

Rekursion: siehe Rekursion.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Programm steigt ohne ersichtlichen Grund aus

Beitrag von Michl »

Komoluna hat geschrieben:aber warum sprint der Debugger dann einfach heraus?
Was meinst Du damit?

Setze ich einen Breakpoint unterhalb dieser Schleife, wird dieser nie erreicht, da in der oben von Dir markierten Zeile eine Schleife ist, in der Du immer eine 0 subtrahierst -> Endlosschleife, das komplette Programm wird außer Gefecht gesetzt.

Ohne jetzt den Code im Einzelnen nachvollzogen zu haben, vermute ich, daß Du Dein Programm am "Laufen" halten halten willst, die Schleife aber nicht beenden. Dazu könntest Du noch ein Application.Prozessmessage; einfügen, dann werden auch die anderen Events (falls vorhanden) abgearbeitet (habs mal getestet, zumindest wird der Code erstmal fortgesetzt, evtl. wird in einem anderen Event Length(m.Items) oder m.Selected geändert - habe es aber nicht geprüft, was Du da kongret wo machst):

Code: Alles auswählen

...
      While m.Selected > Length(m.Items) - 1 Do begin//<<-- Hier Springt der Debugger heraus...
//        writeln(IntToStr(Length(m.Items))+' - '+IntToStr(m.Selected)+' - '+IntToStr(Random(100))); //z.B. so
        m.Selected := m.Selected - Length(m.Items);
        Application.ProcessMessages;
      end;
...

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Komoluna
Beiträge: 565
Registriert: So 26. Aug 2012, 09:03
OS, Lazarus, FPC: Windows(10), Linux(Arch)
CPU-Target: 64Bit

Re: Programm steigt ohne ersichtlichen Grund aus

Beitrag von Komoluna »

Hab das Problem jetzt so gelöst:

Code: Alles auswählen

 
      Case Key Of
        VK_W: m.Selected -= 1;
        VK_S: m.Selected += 1;
        VK_SPACE: Player.Battle.ClickSelectedItem;
      End;
      If length(m.Items) = 0 Then      //<-- Neu...
        exit;                          //<-- Neu...
      While m.Selected > Length(m.Items) - 1 Do
        m.Selected := m.Selected - Length(m.Items);
      While m.Selected < 0 Do
        m.Selected := m.Selected + Length(m.Items);
    Until m.Items[m.Selected].Text <> ''; 
damit hängt das Programm nun in GameClasses.pas Zeile 764 fest, aber das liegt einfach an einer unfertigen Rundenroutine...

Danke an alle, die mitgeholfen haben, das Problem zu lösen...
(aber warum der Debugger aussetzt haben wir noch nicht heraugefunden, oder?)

MFG
Komoluna
Programmer: A device to convert coffee into software.

Rekursion: siehe Rekursion.

martin_frb
Beiträge: 587
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: Programm steigt ohne ersichtlichen Grund aus

Beitrag von martin_frb »

Komoluna hat geschrieben:stimmt, die schleife würde bei einem leeren menü ewig weiterlaufen, aber warum sprint der Debugger dann einfach heraus?
(die schleifen sind dazu da, wenn man z.b. den letzten Menüpunkt ausgewählt hat, und dann "S" drückt, dann soll der erste Menüpunkt ausgewählt werden. )
Eigentlich hast Du Recht. D.h. Ich nehme an du "single stepst" mit F7?

Wahrscheinlich kompilierst du mit -O1 ? (Oder -O2 ?)
O1 ist zwar immer fuer Debuggen empfohlen, hat aber dennoch manchmal Seiten-Effekte. (O2 und Debuggen, ist gar nicht zu empfehlen)

So koennte es ein das O1 den Code

Code: Alles auswählen

 
 While m.Selected > Length(m.Items) - 1 Do
        m.Selected := m.Selected - Length(m.Items);
Irgendwie so um verteilt das alles relevante auf Zeile 1 passiert. (zumindest im falle length=0) F7 versucht dann die naechste Zeile zu erreichen.... (Tja die naechste...)

Probiere mal -O- (no optimization)
-O- unter "Andere Optionen" Im "Custom" Feld eingeben. Fuer den Fall das irgendwo in den Settings die normale Wahl der Optimierungs-Stufe überschrieben wird.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Programm steigt ohne ersichtlichen Grund aus

Beitrag von Michl »

Ich glaube, so kompliziert ist der Sachverhalt nicht.

Probiert man mal

Code: Alles auswählen

var
  i1, i2: Int32;      
...
    i1:=m.Selected;
    i2:=Length(m.Items);
    While m.Selected > Length(m.Items) - 1 Do //hier den Breakpoint gesetzt
        m.Selected := m.Selected - Length(m.Items);
sieht man, dass beim ersten Anspringen des Haltepunktes m.Selected = i1 = 0 und Length(Items) = i2 = 3 ist. Damit wird nicht in die Schleife gesprungen, da 0 nicht größer als 2 ist! Dies tritt erst beim zweiten Durchlauf ein (i1=0 und i2=0, damit ist 0 größer -1), dann springt der Debugger aber auch nicht aus Schleife raus!

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Antworten