Seite 1 von 1

(gelöst) Intwert verändert sich auf unerklärliche Weise

Verfasst: 22.12.2009, 17:36
von FredK
Ich bin folgendes merkwürdiges Problem: Im Moment baue ich meine selbstentwickelte Scriptsprache in mein Spiel ein. Entwickelt und getestet hab ich sie seperat und da hat sie anstandslos funktioniert. Als erste bin ich nun dabei die Eigenschaften der Waffe des Spielers aus dem Script auszulesen. Ich lese also folgendes ein:

Code: Alles auswählen

objekt schwert()
{
wert=100;
meshfile="Schwert.RPMesh";
schlagkraft=20;
name="Einfaches Schwert";
}
Verwaltet wird das nun von einer Klasse Object (mit verbinden werden die Variablenwerte ausgelesen):

Code: Alles auswählen

class object
{
	public:
	variablenmanager instanzvariablen;
	char objektname[256];
	bool verbunden;
	char abgl_von[256];
	bool abgeleitet;

	object::object();
	void verbinden(char *obj_name);
	void Func(const char *name);
};
Die einzelnen Variablen werden von der Klasse Variablenmanger verwaltet (num_var ist die Anzahl der Variablen):

Code: Alles auswählen

struct variable
{
	char varname[256];
	int typ;
	float zahl;
	int laenge;
	char *str;
};

class variablenmanager
{
	public:
	int num_var;
	variable *variablen;

	variablenmanager();
	~variablenmanager();
	void set_str(char vname[256],char* str);
	void set_zahl(char vname[256],float zahl);
	int get_typ(char vname[256]);
	char* get_str(char vname[256]);
	float get_zahl(char vname[256]);
	void get_all_var();
};
Die oben genannten Funktionen kapseln also das Script ab, sodass es im eigentlichen Code recht einfach wird. Das objekt waffe gehört jetzt der Klasse spieler:

Code: Alles auswählen

class spieler
{
public:
	[...]
	void init();
	void render();

	RPMesh schwert;
	object waffe;
	[...]
};
In der Funktion spieler::init() wird das Script gelesen und die Variablen dem Variablenmanager übergeben:

Code: Alles auswählen

void spieler::init()
{
	[...]

	waffe.verbinden("schwert");
        [...]
}

spieler character;
Wenn ich jetzt alle Variablen per this->waffe.instanzvariablen.get_all_var() oder per get_str oder get_int auslese klappt das fehlerfrei. Auch wenn ich dies in spieler::render() mache klappt das. Sobald ich auf eine Variable außerhalb der spieler-klasse zugreifen will (z.B. per character.waffe.instanzvariablen.get_all_var() bzw. [...].get_str() oder [...].get_int()) dann stürzt das Programm ab.
Also

Code: Alles auswählen

this->waffe.instanzvariablen.get_all_var();  //geht problemlos (1)
character.waffe.instanzvariablen.get_all_var();  //stürtz ab (2)
Jetzt hab ich mal ne Testausgabe eingebaut:

Code: Alles auswählen

void variablenmanager::get_all_var()
{
	messageboxEx("Num_Var: %i",num_var);
       [...]
}

Bei (1) liefert sie den korrekten Wert '4'. Bei (2) liefert sie (aus welchen Gründen auch immer) der Wert In der Grüßenordnung von '71270050' der sich jedoch bei jedem Funktionsaufruf ändert. Nun finde ich es absolut unlogisch, warum sich jetzt von der Art des Funktionsaufrufs der Wer von num_var ändert.

Re: Intwert verändert sich auf unerklärliche Weise

Verfasst: 22.12.2009, 17:53
von Aramis
Klarer Fall für einen Debugger. Setz' einen Breakpoint in die fragliche Funktion und schau dir selber an was los ist. printf-Debugging ist nur was für Notfälle, wenn zB. das Anhängen des Debuggers das Programmverhalten komplett ändert (Heisenberg lässt grüßen).

Ich vermute, dass du irgendwie einen Pointer invalidierst oder ein Objekt ausversehen weglöscht.

Re: Intwert verändert sich auf unerklärliche Weise

Verfasst: 22.12.2009, 17:56
von Krishty
Sieht so aus, als würde sich die Deklaration des Spielers für die aufrufende Funktion von der eigentlichen Implementierung unterscheiden … kann passieren, wenn die einzelnen Objektdateien out-of-sync geraten, ein Bekannter hatte letztens das gleiche Problem. Schonmal alles Temporäre gelöscht und ein Rebuild-All probiert?

Ich glaube nicht, dass das Spieler-Objekt zwischendurch versehentlich gelöscht wird, es handelt sich ja – wenn der Beispielcode präzise ist – weder um Zeiger noch um Referenz, sondern um ein Objekt, das nur während seiner Lebenszeit zugänglich ist …

Gruß, Ky

Re: Intwert verändert sich auf unerklärliche Weise

Verfasst: 22.12.2009, 18:29
von FredK
Ich hab eine komplette Neukompilation schon versucht, jedoch ohne Erfolg.
Grade, dass es ja ein Objekt ist, das auf keinster Weise dynamisch ist macht mich ja so stutzig.

Re: Intwert verändert sich auf unerklärliche Weise

Verfasst: 22.12.2009, 18:34
von Krishty
An #pragma pack oder dem Struct Member Alignment hast du auch nicht rumgespielt?

Im Debugger würde ich mir als erstes anschauen, ob der Zeiger auf character (einmal this, das andere Mal &character) bei den beiden verschiedenen Aufrufen gleich ist und wie weit er auf gültige Daten zeigt.

Re: Intwert verändert sich auf unerklärliche Weise

Verfasst: 22.12.2009, 18:43
von Stefan Zerbst
Hi,

also wenn das get_all_var (was auch immer das macht, ich vermute es versucht auf irgendeinem Weg das Attribut *variablen zu füllen) crasht bzw. in der Ausgabe vorher immer einen anderen Wert zeigt dann deutet das auf eine kaputte Instanz von Object hin. Der Wert ändert sich weil du durch die Verwendung eine kaputten Objects auf eine beliebige Adresse im Speicher zugreifst und dann eben den Wert bekommst der da gerade so steht.

Der Crash kommt wohl daher, dass du versuchst mehr mit den Attributen des Managers eines kaputten Objects zu machen als der Speicher aushält. Aus dem gegebenen Code kann man wenig mehr sagen. Du solltest mal genau debuggen und vor allem schauen ob die Adressen von "character" und "this" auch wirklich gleich sind. Vielleicht wurde irgendwo implizit ein Default-Copy Constructor verwendet um die Variable "character" anzulegen? Das würde als Erklärung für die Phänomene schon ausreichen ...

Ciao,
Stefan

Edit Mist ich tippe zu langsam, Krishty war schneller :mrgreen:

Re: Intwert verändert sich auf unerklärliche Weise

Verfasst: 22.12.2009, 19:00
von Krishty
Mich irritiert, dass keines der Objekte, durch die sich der Aufruf wuselt, indirekt referenziert wird. Wenn num_vars also in ungültigem Speicher liegt, muss bereits character in ungültigem Speicher liegen (was unwahrscheinlich ist, weil auch character gemäß Deklaration entweder eine lokale Variable oder ein direktes Member ist) – oder der Compiler versagt dabei, die Offsets der Member zu bestimmen (was bei unterschiedlichen Quelldateien schonmal passieren kann, aber nach einem komplett-Rebuild nicht vorkommen dürfe). Selbst, wenn das Objekt zwischendurch zerstört würde, müsste num_vars noch die richtige Anzahl anzeigen, weil ein D’tor gewöhnlich nicht Member-Variablen mit 71270050 überschreibt.

Oder FredK verschweigt uns, dass eines der Objekte eben doch per Zeiger/Referenz adressiert wird?

Re: Intwert verändert sich auf unerklärliche Weise

Verfasst: 22.12.2009, 19:08
von FredK
Nönö ich verschweig euch gar nichts.
Der #pargma pack war es. Wäre da selbst nie drauf gekommen. Ich hatte in meinem Code zum Laden der Milkshapedateien drin stehen:

Code: Alles auswählen

#pragma pack( push, packing )
#pragma pack( 1 )
#define PACK_STRUCT
Wenn ich jetzt das alles ausklammere, ist funktioniert alles, bis auf das Laden der Milkshapedateien. Ich hatte meinen Loader nach dem Tutorial von Bratt Porter in DirectX, statt er in OpenGL geschrieben. Da ich die obrigen Zeilen nicht verstanden hab, hab ich sie einfach übernommen. Blöderweise weis ich jetzt auch nicht, wie ich die Auswirkungen auf den Milkshapeloader begrenze.

Re: Intwert verändert sich auf unerklärliche Weise

Verfasst: 22.12.2009, 19:12
von Krishty
Das regelt, wie nah die Member in Datenstrukturen aneinander gepackt werden sollen (weil der Compiler normalerweise Füllbytes unterbringt, wenn der Zugriff dadurch schneller wird). Der Code bedeutet, dass von nun an alle structs, die deklariert werden, an einzelnen Bytes ausgerichtet werden (also keine Füllbytes mehr untergebracht werden – was nützlich ist, wenn man Dateien damit schreibt, weil unterschiedliche Kompilate möglicherweise unterschiedlich füllen würden und dann genau der Fehler geschähe, wegen dem du diesen Thread eröffnet hast).

Lass die Zeile stehen und schreib ans Ende vom Milkshape-Loader #pragma pack(pop, packing). Dann setzt der Compiler die Option für den Rest deines Programms auf die vorherige Einstellung zurück und alle sind glücklich :)

Re: Intwert verändert sich auf unerklärliche Weise

Verfasst: 22.12.2009, 19:17
von Schrompf
Das kann aber auch bedeuten, dass Du *irgendwo* im Speicher über die Grenzen eines Objekts hinausschreibst und das geänderte Pack-Pragma jetzt nur das Speicherlayout so verschoben hat, dass der Fehler wieder verdeckt ist. Behalte die Geschichte im Auge, die kann später mal schmerzhaft zurückkommen.

Re: Intwert verändert sich auf unerklärliche Weise

Verfasst: 22.12.2009, 19:21
von Krishty
Das ist sicher nicht unmöglich – es sieht aber so aus, als sei die Klasse spieler ziemlich schwer … wenn irgendwo wild geschrieben würde, wäre es sehr unwahrscheinlich, dass ausgerechnet und ausschließlich die eine int in der Mitte getroffen wurde. Im Auge behalten ist aber immer gut.

Re: Intwert verändert sich auf unerklärliche Weise

Verfasst: 22.12.2009, 19:25
von FredK
Vielen Dank. Damit ist das Problem gelöst. Bestenfalls hat sich jetzt auch nen anderes Problem mitgelöst (nen Gegner positionierte sich manchmal falsch), in das ich auch schon viele Stunden Arbeit investiert habe.