ListIndex() führt zu Tod des Programms

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Chimorin
Beiträge: 451
Registriert: 30.01.2013 16:11
Computerausstattung: MSI GTX 660 OC mit TwinFrozr III
6Gb DDR 3 RAM
AMD Phenom II X4 B55 @ 3,6GHz
Windows 7 Home Premium 64-bit

ListIndex() führt zu Tod des Programms

Beitrag von Chimorin »

Heyho,

derzeit habe ich einen kuriosen Fehler in meinem Programm. Ich füge einer Liste ein Element hinzu und möchte gleich danach den Index (Die Position in der Liste) haben.
In meinem Vorzeigeprogramm funktioniert es einwandfrei, nur in meinem richtigen Programm nicht. Ich poste mal Beides.

Hattet ihr auch schon einmal so etwas? Ich frage mich, wo ich da ansetzen soll, ich meine, ich arbeite ohne Threads und der Fehler ist einfach kurios Oo
Das Programm friert einfach ein, Windows meldet dann keine Rückmeldung. Durch etliche Debug habe ich dann herausgefunden, dass es nach ListIndex() einfach nicht mehr weitergeht im Programmablauf.

1. Verdacht: Comodo
Nein, ist es nicht, nach abgeschaltenem Comodo tritt das Problem weiterhin auf.


Hier einmal der Programmschnipsel, in dem das Problem auftritt (Nicht lauffähig):

Code: Alles auswählen

              With terrain(terAlt\x, terAlt\y)
                ;Das "Verschieben" des Verwaltungsteils des Baumes.
                ;SelectElement(\Baeume(), entList()\zugehoer)
                ChangeCurrentElement(\Baeume(), entList()\zeiger)
                ;SuchBaumPlatz(terrainX, terrainY)
                AddElement(terrain(terrainX, terrainY)\Baeume())
                Debug "terrainX:" + terrainX + "terrainY:" + terrainY
                Debug ListIndex(terrain(terrainX, terrainY)\Baeume())        ;-XXXXXXXXXXXXXXXXXXX Hier Tod
                Debug "öo"
                terrain(terrainX, terrainY)\Baeume()\wurzel = \Baeume()\wurzel
                terrain(terrainX, terrainY)\Baeume()\stamm = \Baeume()\stamm
                terrain(terrainX, terrainY)\Baeume()\blaetter = \Baeume()\blaetter
                For zaehler = 0 To #AesteMax
                  If \Baeume()\aeste[zaehler]\meshID = #True
                    terrain(terrainX, terrainY)\Baeume()\aeste[zaehler]\meshID = #True
                    terrain(terrainX, terrainY)\Baeume()\aeste[zaehler]\entNr = \Baeume()\aeste[zaehler]\entNr
                    
                  Else
                    terrain(terrainX, terrainY)\Baeume()\aeste[zaehler]\meshID = #False
                    
                  EndIf
                Next zaehler
                terrain(terrainX, terrainY)\Baeume()\lebenPunkte\akt = \Baeume()\lebenPunkte\akt
                terrain(terrainX, terrainY)\Baeume()\lebenPunkte\max = \Baeume()\lebenPunkte\max
                terrain(terrainX, terrainY)\Baeume()\lebenZeit\akt = \Baeume()\lebenZeit\akt
                terrain(terrainX, terrainY)\Baeume()\lebenZeit\max = \Baeume()\lebenZeit\max
                terrain(terrainX, terrainY)\Baeume()\lebenZeit\stufe = \Baeume()\lebenZeit\stufe
                terrain(terrainX, terrainY)\Baeume()\typ = \Baeume()\typ
                ;\Baeume()\typ = #BI_None       ;-OOOOOOOOOOOOOOOOOOOOOOOOO Hier den Rest auch noch auf "0" setzen.
                
                ;Das "Verschieben" der Objektlisteneinträgen
                Debug "0"
                zugehoer = ListIndex(terrain(terrainX, terrainY)\Baeume())
                Debug "1"
Hier ein lauffähiges Programm (Getestet, funktioniert ; Soll den Ablauf darstellen):

Code: Alles auswählen

EnableExplicit


Structure Vektor2i
  x.i
  y.i
EndStructure


Structure treeVer
  nummer.i
EndStructure


Structure obVer
  zeiger.i
  string.s
EndStructure


Structure terVer
  ;inVer.i
  List Objekte.obVer()
  List Baeume.treeVer()
EndStructure


Dim test.terVer(1, 1)
;NewList temp.i()
Define.Vektor2i terAlt, terNeu
Define.i temp

terNeu\x = 1
terNeu\y = 1


;Fill
With test(terAlt\x, terAlt\y)
  AddElement(\Baeume())
  \Baeume()\nummer = 1
  AddElement(\Objekte())
  \Objekte()\zeiger = @\Baeume()
  \Objekte()\string = "1"
  
  AddElement(\Baeume())
  \Baeume()\nummer = 2
  AddElement(\Objekte())
  \Objekte()\zeiger = @\Baeume()
  \Objekte()\string = "2"
EndWith


;Use
; AddElement(temp())
SelectElement(test(terAlt\x, terAlt\y)\Objekte(), 1)
temp = test(terAlt\x, terAlt\y)\Objekte()\zeiger
; temp() = @\Baeume()


;Move
With test(terAlt\x, terAlt\y)
  ChangeCurrentElement(\Baeume(), temp)
  AddElement(test(terNeu\x, terNeu\y)\Baeume())
  Debug ListIndex (test(terNeu\x, terNeu\y)\Baeume())
EndWith


;Use
; AddElement(temp())
SelectElement(test(terAlt\x, terAlt\y)\Objekte(), 0)
temp = test(terAlt\x, terAlt\y)\Objekte()\zeiger
; temp() = @\Baeume()


;Move
With test(terAlt\x, terAlt\y)
  ChangeCurrentElement(\Baeume(), temp)
  AddElement(test(terNeu\x, terNeu\y)\Baeume())
  Debug ListIndex (test(terNeu\x, terNeu\y)\Baeume())
EndWith

End
__________________________________________________
Thread verschoben
Bugs>Allgemein
27.02.2014
RSBasic
Bild

- formerly known as Bananenfreak -
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7039
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: ListIndex() führt zu Tod des Programms

Beitrag von STARGÅTE »

Das es im Beispiel geht und in deinem Programm nicht, würde dafür sprechen, dass der Fehler bereits vorher passiert und einfach nur der Header der LinkedList zerstört wird, was dann zu einem Fehler bei ListIndex führt.

Hast du mal den Purifier angeschaltet um zu sehen, ob es einen MemoryOverflow gibt?
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Chimorin
Beiträge: 451
Registriert: 30.01.2013 16:11
Computerausstattung: MSI GTX 660 OC mit TwinFrozr III
6Gb DDR 3 RAM
AMD Phenom II X4 B55 @ 3,6GHz
Windows 7 Home Premium 64-bit

Re: ListIndex() führt zu Tod des Programms

Beitrag von Chimorin »

Ich habe ihn (den Purifier) eingeschaltet, er gibt aber nichts zurück...

Wie kann es passieren, dass der Header zerstört wird?

Noch etwas: AddElement() gibt eine Zahl größer 0 zurück, somit funktioniert das einwandfrei...

EDIT: Naja, ich habe es umgeschrieben, ListIndex() benötige ich an dieser Stelle nicht mehr. Ich habe es aber mal als Kommentar drinnen gelassen, vllt hat noch jemand eine Lösung parat... (Es könnte sich ja um einen arglistigen Bug in meinem Programm handeln oder sogar um einen in PB)
Bild

- formerly known as Bananenfreak -
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7039
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: ListIndex() führt zu Tod des Programms

Beitrag von STARGÅTE »

Bananenfreak hat geschrieben:Wie kann es passieren, dass der Header zerstört wird?
zB. wenn du PokeX() Befehle verwendest und in einen Speicher schreibst, der eigentlich nicht dir gehört.
zB. wenn du CopyStructure verwendest, aber die Structure nicht passt.

Oder du hast mit ChangeCurrentElement() das Element gewechselt, aber der Pointer ist garnicht mehr gültig, dann würde ListIndex danach auch nicht funktionieren.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Chimorin
Beiträge: 451
Registriert: 30.01.2013 16:11
Computerausstattung: MSI GTX 660 OC mit TwinFrozr III
6Gb DDR 3 RAM
AMD Phenom II X4 B55 @ 3,6GHz
Windows 7 Home Premium 64-bit

Re: ListIndex() führt zu Tod des Programms

Beitrag von Chimorin »

Aha, ich bin gerade am Umstellen von SelectElement() auf ChangeCurrentElement(). Dann liegt hier also irgendwo der Schlússel.

Wenn ich eine Liste mit 4 Elementen habe, von jedem Element den Zeiger gespeichert habe und das 2. Element lösche, dann sind ja noch alle Zeiger bis auf den Zeiger auf das 2. Element gültig, oder? (Ich habe dazu ein Programm geschrieben, ja, es ist so, aber vllt kann sich der Zeiger ja doch ändern...) Wenn ich nun versuche ChangeCurrentElement() mit dem Zeiger auf das 2. Element zu benutzen, müsste mir doch PB melden, dass das nicht gehen würde, oder?

Edit: Hmm, wenn ich spaeter am PC bin, muss ich mal meinen Testcode posten. Ich benutze ChangeCurrentElement() mit Variablen, nicht mit einem Zeiger. Aber so, wie ich das gelesen habe, soll das ja dann falsch sein.

Edit2: Oder doch nicht? Das macht ja bei ChangeCurrentElement() primär keinen Unterschied...
Bild

- formerly known as Bananenfreak -
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7039
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: ListIndex() führt zu Tod des Programms

Beitrag von STARGÅTE »

Bananenfreak hat geschrieben:Wenn ich eine Liste mit 4 Elementen habe, von jedem Element den Zeiger gespeichert habe und das 2. Element lösche, dann sind ja noch alle Zeiger bis auf den Zeiger auf das 2. Element gültig, oder?
Richtig. Und das 3. und 4. Element wird zum neuen 2. und 3. Element, ändern jedoch nicht ihre Adressen.
Bananenfreak hat geschrieben:Wenn ich nun versuche ChangeCurrentElement() mit dem Zeiger auf das 2. Element zu benutzen, müsste mir doch PB melden, dass das nicht gehen würde, oder?
Nein. ChangeCurrentElement() wurde auf schnelligkeit optimiert, dass bedeutet, es erfolgt keine Abfrage auf Gültigkeit der übergebenen Adresse. Das 2. Element kann sogar noch vollständig im Speicher vorhanden sein (da der Speicher bei DeleteElement nicht zwangsweise komplett geleert wird), sodass es vielleicht im ersten Moment noch keinen Fehler gibt, sondern erst Später, wenn der Speicher von einem neuen 5. Element besetzt wird und es dann zB zu einem zirkulären Bezug kommt.
Der Index eines Listenelements ist ja für das Element selbst unbekannt. Es wird bei ListIndex() also vom ersten Element solange gesprungen, bis das aktuelle Element kommt.
Bananenfreak hat geschrieben:Edit2: Oder doch nicht? Das macht ja bei ChangeCurrentElement() primär keinen Unterschied...
ChangeCurrentElement() verlangt eine Adresse zu einem gültigen Element.
Diese Adresse kanst du in einer Integer speichern, oder in einem Pointer.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Chimorin
Beiträge: 451
Registriert: 30.01.2013 16:11
Computerausstattung: MSI GTX 660 OC mit TwinFrozr III
6Gb DDR 3 RAM
AMD Phenom II X4 B55 @ 3,6GHz
Windows 7 Home Premium 64-bit

Re: ListIndex() führt zu Tod des Programms

Beitrag von Chimorin »

Danke für die ausführlichen Antworten, Stargate.

Nur eins... Hier mal ein Zitat aus "F1" (^^) zu ListIndex():
Diese Funktion ist sehr schnell und kann ohne Performanzverlust auch häufig verwendet werden (sie durchläuft nicht jedes Mal die gesamte Liste, sondern nutzt einen zwischengespeicherten Wert)
ListIndex durchläuft somit nicht die gesamte Liste, aber wie entsteht der zwischengespeicherte Wert? Eventuell kann ich da ja einklinken...

EDIT: So, gelöst. Es lag an... NICHTS. Ich habe gerade gedacht "Ach, schauen wir das doch nochmal an". Gesagt, getan, nochmal die Kommentare rausgemacht, gestartet. Funktion ausgeführt... Kein Problem. Manchmal komme ich mir irgendwie dumm vor, so als ob jemand nachts in meinem Code rumwuseln würde :D
Bild

- formerly known as Bananenfreak -
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: ListIndex() führt zu Tod des Programms

Beitrag von ts-soft »

Da es sich hierbei offentsichtlich nicht um einen Bug in PB handelt, sollte der Thread am besten
nach Allgemein verschoben werden!

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7039
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: ListIndex() führt zu Tod des Programms

Beitrag von STARGÅTE »

Bananenfreak hat geschrieben:Nur eins... Hier mal ein Zitat aus "F1" (^^) zu ListIndex():
Diese Funktion ist sehr schnell und kann ohne Performanzverlust auch häufig verwendet werden (sie durchläuft nicht jedes Mal die gesamte Liste, sondern nutzt einen zwischengespeicherten Wert)
ListIndex durchläuft somit nicht die gesamte Liste, aber wie entsteht der zwischengespeicherte Wert? Eventuell kann ich da ja einklinken...
Was in der Hilfe steht ist so gemeint:
Wenn du einmal ListIndex aufgerufen hast (wo die gesamte Liste durchlaufen wurde) dann wird der Index zum Element "zwischengespeichert". Ein weiterer Aufruf nutzt diesen Wert dann auch wieder.
Auch wenn NextElement ausgeführt wird, wird der Index einfach für das nächste Element um 1 erhöht.
Aber sobald sich die Reihenfolge der Elemente (massiv) ändert (Delete, Add, Swap), werden diese Zwischenspeicher ungültig, und es wird wieder von vorne gerechnet, bzw. von dem Element, deren Index noch gültig ist.

Wenn du zuverlässig und Schnell zwischen Elementen Wechseln willst, ist ChangeCurrentElement() die bessere Wahl, als ListIndex und SelectElement().
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Antworten