[gelöst] For-Schleifenvariable nicht im sinnvollen Bereich

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
bleistift2
Beiträge: 10
Registriert: Di 21. Okt 2014, 17:57
OS, Lazarus, FPC: Windows 7 Professional SP1 64bit; Lazarus 1.2.6

[gelöst] For-Schleifenvariable nicht im sinnvollen Bereich

Beitrag von bleistift2 »

Morgen,

ich musste vor kurzer Zeit zu Lazarus wechseln, da meine Schule nicht mehr mit Delphi 5 unterrichtet. Ich bin also ziemlich unerfahren im Umgang mit Lazarus, habe aber schon etwas Pascal-Erfahrung. Zur Zeit programmiere ich einen Sudoku-Löser. Nachdem die vorgegebenen Ziffern in ein Array geschrieben wurden, soll das Programm jedes Feld durchgehen und prüfen, ob dort eine Zahl steht. Ist dem so, wird diese Zahl aus den Möglichkeiten für die Felder mit der gleichen X-Koordinate, Y-Koordinate und demselben 3×3-Kasten gelöscht. Das ganze steht in einer Repeat-Schleife, die nach jedem Durchgang prüft, ob ein neues Feld gelöst wurde und abbricht, wenn dem nicht so ist.

Das Problem ist nun, dass die zweite For-Schleife (For Y := 1 to 9 do) mit unsinnigen Werten zählt. Es scheint, als würde sie die Schleifenvariable nicht initialisieren. Lasse ich sie nämlich auslesen, indem ich den Coursor drüberhalte, stehen da z.B. Werte von 777, 769 oder 771, was theoretisch nicht einmal möglich sein sollte, da Y als Integer-Teilbereich von 0 bis 9 deklariert ist. Es kommt auch keine Zugriffsverletzung, wenn das Programm dann auf Matrix[X, 777] zugreifen soll. Kann mir jemand sagen, was ich damit anfangen soll? Das Programm funktioniert zwar nicht richtig, aber ich würde meine Hand nicht dafür ins Feuer legen, dass es daran liegt.

Danke im Voraus.

Code: Alles auswählen

 
  Zahlen9 = 0..9;
  Menge9 = Set of Zahlen9;
  Zelle9 = Record Eintrag: Zahlen9;
                  Moeglichkeiten: Menge9;
                  End;
  Matrix9 = Array[1..9] of Array [1..9] of Zelle9;
 

Code: Alles auswählen

 
Procedure Eliminieren(Var Matrix: Matrix9); Overload; //Löst das Sudoku durch Ausschließen von Lösungsmöglichkeiten
Var X, Y, I: Zahlen9;
    Geloest: Byte;
Begin
  Repeat
    Schnellausgabe(Matrix, 'vor Loesen'); //Gibt die Matrix in einer Messagebox aus
    Geloest := Loesungenzaehlen(Matrix);//Zum Zählen der vor dem Ausschließen gelösten Felder
    For X := 1 to 9 do
      For Y := 1 to 9 do
        If Matrix[X, Y].Eintrag <> 0 Then Begin //steht eine Zahl im aktuellen Feld? (0 = kein Eintrag)
          For I := 1 to 9 do Begin
            Matrix[I, Y].Moeglichkeiten := Matrix[I, Y].Moeglichkeiten - [Matrix[X, Y].Eintrag]; //Eliminieren der Möglichkeiten in derselben Zeile
            Matrix[I, Y] := EintragDeterminiert(Matrix[I, Y]); //Gibt es nur noch eine Möglichkeit, wird sie in das Feld eingetragen
            Matrix[X, I].Moeglichkeiten := Matrix[X, I].Moeglichkeiten - [Matrix[X, Y].Eintrag]; //Eliminieren der Möglichkeiten in derselben Spalte
            Matrix[X, I] := EintragDeterminiert(Matrix[X, I]);
            End;
          Matrix := Kasteneliminierung(Matrix, X, Y);//Entfernt Möglichkeiten aus den Feldern des 3×3-Kastens
          End;
    Schnellausgabe(Matrix, 'nach Loesen');
  until Loesungenzaehlen(Matrix) = Geloest; //Abbruch der Schleife, wenn keine neue Lösung dazugekommen ist.
end;
Zuletzt geändert von bleistift2 am Mo 27. Okt 2014, 16:38, insgesamt 1-mal geändert.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2640
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: For-Schleifenvariable außerhalb des sinnvollen Bereiches

Beitrag von m.fuchs »

Hm, kannst du mal ein kompilierbares Minimalbeispiel hochladen, bei dem der Fehler auftritt?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

bleistift2
Beiträge: 10
Registriert: Di 21. Okt 2014, 17:57
OS, Lazarus, FPC: Windows 7 Professional SP1 64bit; Lazarus 1.2.6

Minimalbeispiel

Beitrag von bleistift2 »

Hier habe ich alle Prozeduren gelöscht, die für den Programmablauf, in dem der Fehler vorkommt, nicht notwendig sind. Die oben zitierte Prozedur ist bei Zeile 330. Wenn ich in einem anderen Programm Schleifen verschachtele, funktioniert alles wunderbar.

Ich habe zur Sicherheit alle Dateien, die in dem Ordner von Lazarus erzeugt wurden, in das angehängte Archiv gepackt. Welche genau wären nötig gewesen?
Dateianhänge
Sudoku Mini.rar
(2.97 MiB) 33-mal heruntergeladen

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2640
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: For-Schleifenvariable außerhalb des sinnvollen Bereiches

Beitrag von m.fuchs »

Wenn du X, Y und I auf dem Typ Integer umstellst, sollte das Problem verschwinden. Zumindest funktioniert es seitdem bei mir. Frag mich aber nicht, warum.
Notwendig ist die Beschränkung an dieser Stelle nicht.

bleistift2 hat geschrieben:Ich habe zur Sicherheit alle Dateien, die in dem Ordner von Lazarus erzeugt wurden, in das angehängte Archiv gepackt. Welche genau wären nötig gewesen?

Auf backup, libs und die *.exe kann man verzichten.

Übrigens: gibt es einen Grund dafür, dass du so viele Prozeduren mit overload kennzeichnest?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

bleistift2
Beiträge: 10
Registriert: Di 21. Okt 2014, 17:57
OS, Lazarus, FPC: Windows 7 Professional SP1 64bit; Lazarus 1.2.6

Re: For-Schleifenvariable außerhalb des sinnvollen Bereiches

Beitrag von bleistift2 »

m.fuchs hat geschrieben:Übrigens: gibt es einen Grund dafür, dass du so viele Prozeduren mit overload kennzeichnest?

Ja, denn eigentlich kann das Programm zwei „Layouts” lösen, einmal das klassische (3×3)×(3×3) und ein (2×4)×(2×4). Die einzelnen aufgerufenen Prozeduren gibt es dann einmal für jede Variante.

m.fuchs hat geschrieben:Wenn du X, Y und I auf dem Typ Integer umstellst, sollte das Problem verschwinden. Zumindest funktioniert es seitdem bei mir.

Das Problem verschwindet in der Tat. Mein Programm funktioniert zwar immer noch nicht so, wie es soll, aber jetzt kann ich mir wenigstens sicher sein, dass der Fehler nicht da liegt ^^
Mich verwundert, dass dieselbe Prozedur für das zweite Layout perfekt funktioniert, obwohl da praktisch genau dasselbe steht.

Code: Alles auswählen

 
Procedure Eliminieren(Var Matrix: Matrix8); Overload; //Löst das Sudoku durch Ausschließen von Lösungsmöglichkeiten
Var X, Y, I: Zahlen8;
    Geloest: Byte;
Begin
  Repeat
    Geloest := Loesungenzaehlen(Matrix); //Speichern der Anzahl der aktuell gelösten Felder für den späteren Vergleich
    For X := 1 to 8 do
      For Y := 1 to 8 do
        If Matrix[X, Y].Eintrag <> 0 Then Begin //Feld ist gelöst
          For I := 1 to 8 do Begin
            Matrix[I, Y].Moeglichkeiten := Matrix[I, Y].Moeglichkeiten
                                         - [Matrix[X, Y].Eintrag];
            Matrix[I, Y] := EintragDeterminiert(Matrix[I, Y]); // Entferne Eintrag der aktuellen Zelle aus den Möglichkeiten aller anderen Zellen der Zeile
            Matrix[X, I].Moeglichkeiten := Matrix[X, I].Moeglichkeiten
                                         - [Matrix[X, Y].Eintrag];
            Matrix[X, I] := EintragDeterminiert(Matrix[X, I]); // Entferne Eintrag der aktuellen Zelle aus den Möglichkeiten aller anderen Zellen der Spalte
            End;
          Matrix := Kasteneliminierung(Matrix, X, Y); // Entferne Eintrag der aktuellen Zelle aus den Möglichkeiten aller anderen Zellen des Kastens
          end;
 
  until Loesungenzaehlen(Matrix) = Geloest; //Prüfen, ob bei diesem Durchgang ein neues Feld gefüllt wurde
end;   
 

m.fuchs hat geschrieben:Frag mich aber nicht, warum.

Hast du vielleicht eine leise Ahnung, was da schiefgeht?

Auf jeden Fall DANKE für die schnelle Hilfe!
Zuletzt geändert von bleistift2 am Mo 27. Okt 2014, 16:43, insgesamt 1-mal geändert.

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

Re: For-Schleifenvariable außerhalb des sinnvollen Bereiches

Beitrag von Michl »

Hallo bleistift2,

ich habe mir eben Dein Problem in Deinem Programm angesehen. Mit "...Lasse ich sie nämlich auslesen, indem ich den Coursor drüberhalte..." meinst Du sicherlich, indem Du diese Zeile debuggst.
Daß dort falsche Werte angezeigt werden, hat wahrscheinlich weniger etwas mit Lazarus/FreePascal zu tun, als daß der extern genutzte Debugger Probleme hat, die Werte richtig zu deuten (unter Win7, 64bit, Lazarus 32bit 1.2.4 konnte ich diese Fehldeutung sehen, unter Lazarus 1.3 nicht - Fehler kann evtl. in der Entwicklerversion schon behoben wurden sein - ich nutze die gleiche GDB-Version).
Generell brauchst Du Dir über diese Fehlmeldung des Debuggers keine Sorgen machen, ein Test, wie:

Code: Alles auswählen

...
        If Matrix[X, Y].Eintrag <> 0 Then Begin
          if (x > 9) or (y > 9) then ShowMessage('Größerer Wert als 9');
...
hatte bei mir keine Meldung hervorgerufen.

PS: als Zählvariablen würde ich allerdings, wie m.fuchs auch schon schrieb, lieber einen ganzzahligen Datentyp, als einen Teilbereichstyp wählen. Damit dürfte dann auch der Debugger keine Probleme damit haben.

Code: Alles auswählen

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

bleistift2
Beiträge: 10
Registriert: Di 21. Okt 2014, 17:57
OS, Lazarus, FPC: Windows 7 Professional SP1 64bit; Lazarus 1.2.6

Re: For-Schleifenvariable außerhalb des sinnvollen Bereiches

Beitrag von bleistift2 »

Michl hat geschrieben:ich habe mir eben Dein Problem in Deinem Programm angesehen. Mit "...Lasse ich sie nämlich auslesen, indem ich den Coursor drüberhalte..." meinst Du sicherlich, indem Du diese Zeile debuggst.
In der Tat. Tut mir Leid, dass ich mich mit der Terminologie auch nicht wirklich auskenne. Die Frage bei der Registrierung, was die Abkürzung für „Integrierte Entwicklungsumgebung” sei, habe ich auch nur durch das Raten der Übersetzung gelöst. :oops:

Michl hat geschrieben:Generell brauchst Du Dir über diese Fehlmeldung des Debuggers keine Sorgen machen, ein Test, wie:

Code: Alles auswählen

...
        If Matrix[X, Y].Eintrag <> 0 Then Begin
          if (x > 9) or (y > 9) then ShowMessage('Größerer Wert als 9');
...
hatte bei mir keine Meldung hervorgerufen.

Ich hatte da auch keinen Fehler festgestellt. Der lag in einem fehlenden Rückgabewert einer Funktion, was ich aber lange nicht bemerkte. Daher dachte ich, es könnte eventuell doch an diesen komischen Werten liegen.

Michl hat geschrieben:Daß dort falsche Werte angezeigt werden, hat wahrscheinlich […damit] zu tun, […] daß der extern genutzte Debugger Probleme hat, die Werte richtig zu deuten

Dafür spricht, dass beim Debuggen immer dieselben „falschen” Werte angezeigt wurden. Ich werde mal die neueste Version installieren. Schaden sollte es ja nicht können.

Nochmal danke für die Hilfe!

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: [gelöst] For-Schleifenvariable nicht im sinnvollen Berei

Beitrag von mse »

bleistift2 hat geschrieben:Das Problem ist nun, dass die zweite For-Schleife (For Y := 1 to 9 do) mit unsinnigen Werten zählt. Es scheint, als würde sie die Schleifenvariable nicht initialisieren. Lasse ich sie nämlich auslesen, indem ich den Coursor drüberhalte, stehen da z.B. Werte von 777, 769 oder 771, was theoretisch nicht einmal möglich sein sollte, da Y als Integer-Teilbereich von 0 bis 9 deklariert ist.

Probiere mal mit ausgeschalteter Optimierung (-O- und das erste mal zusätzlich -B) zu kompilieren. Beim Debuggen mit gdb gibt es mit -O2, -O3 und manchmal auch mit -O1 Probleme.

bleistift2
Beiträge: 10
Registriert: Di 21. Okt 2014, 17:57
OS, Lazarus, FPC: Windows 7 Professional SP1 64bit; Lazarus 1.2.6

Re: [gelöst] For-Schleifenvariable nicht im sinnvollen Berei

Beitrag von bleistift2 »

mse hat geschrieben:Probiere mal mit ausgeschalteter Optimierung (-O- und das erste mal zusätzlich -B) zu kompilieren. Beim Debuggen mit gdb gibt es mit -O2, -O3 und manchmal auch mit -O1 Probleme.


Ich wollte Dir erst antworten, dass der Fehler nun gar nicht mehr auftritt (seit das Programm einwandfrei läuft), aber ich wollte es doch noch einmal probieren, und siehe da: Die Variable X, mittlerweile Integer, zeigt wieder abstruse Werte, jetzt aber 1.999.845.377, …378, …379, …380, …, während Y korrekt zählt. Das Programm läuft trotzdem perfekt.

Daran ändert sich nichts, wenn ich in die erste Zeile {%-O}{%-B} schreibe oder in den Projekteinstellungen unter Compilereinstellungen/Kompilieren und Linken die Optimierung auf Stufe 0 stelle. (Ich weiß leider nicht genau, was Du mit „-B“ meinst und hoffe, dass ich dem mit diesem {%-B} nachgekommen bin. Wenn nicht, erkläre mir bitte nochmal genau, was ich tun soll.)

Kann es vielleicht daran liegen, dass ich Lazarus mittlerweile aktualisiert habe? Ich glaube nämlich, dass es noch unter der alten Version war, als die Variablen sinnvolle Werte anzeigten.

Erneut danke für das ungebrochene Interesse an der „Problem“lösung und entschuldigung, dass ich so lange nichts von mir hören ließ.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: [gelöst] For-Schleifenvariable nicht im sinnvollen Berei

Beitrag von mse »

Die FPC Kommando Zeilen Parameter sind hier beschrieben:
http://www.freepascal.org/docs-html/use ... 4-410005.1
-B führt dazu, dass alle erreichbaren units kompiliert werden damit das Ausschalten der Optimierung durch -O- im ganzen Programm durchgeführt wird, 'Build' statt 'Make' sollte den gleichen Effekt haben. Ohne -B werden nur die geänderten units kompiliert.
Es kann auch sein, dass Lazarus die Änderungen der Kompilieroptionen überwacht und von sich aus beim nächsten Übersetzen -B einfügt.
Im Zweifelsfall empfiehlt es sich, die erzeugten Parameter mit dem button 'Show Options' zu kontrollieren.
Das mit {%-O} und {%-B} verstehe ich nicht. Ist das eine Lazarus Funktion? Die {$xxx} FPC Direktiven sind hier beschrieben:
http://www.freepascal.org/docs-html/pro ... l#x5-40001
Edit: Noch ein Hinweis, "Optimierung auf Stufe 0 stellen" fügt kein -O- ein, sondern unterlässt das Einfügen von -O1, -O2 oder -O3. Ein eventuell vorhandenes -On in der cfg-Datei wird dadurch nicht ausser Kraft gesetzt. Sicherheitshalber muss man in 'Compiler Options'-'Other'-'Custom options' -O- eintragen.

bleistift2
Beiträge: 10
Registriert: Di 21. Okt 2014, 17:57
OS, Lazarus, FPC: Windows 7 Professional SP1 64bit; Lazarus 1.2.6

Re: [gelöst] For-Schleifenvariable nicht im sinnvollen Berei

Beitrag von bleistift2 »

mse hat geschrieben:Das mit {%-O} und {%-B} verstehe ich nicht. Ist das eine Lazarus Funktion?

Ich dachte, Du meintest mit -O und -B Compilerdirektiven und habe sie deshalb in den Quelltext geschrieben:

Code: Alles auswählen

unit unit1 {%-O}{%-B}

Ich weiß wiederum nicht, was du mit „'Build' statt 'Make'“ meinst (ich nutze die deutsche Version).
Aber auch, wenn ich in den Projekteinstellungen/Compilereinstellungen/Andere den Benutzerdefinierten Einstellungen -O- und -B hinzufüge, neu kompiliere und starte, tritt der Fehler auf, aber mit anderen Werten.

Antworten