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

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
FredK
Beiträge: 31
Registriert: 06.05.2004, 17:11

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

Beitrag 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.
Zuletzt geändert von FredK am 22.12.2009, 19:27, insgesamt 1-mal geändert.
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

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

Beitrag 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.
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

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

Beitrag 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
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
FredK
Beiträge: 31
Registriert: 06.05.2004, 17:11

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

Beitrag 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.
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

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

Beitrag 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.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Stefan Zerbst
Moderator
Beiträge: 189
Registriert: 25.02.2009, 19:54

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

Beitrag 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:
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

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

Beitrag 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?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
FredK
Beiträge: 31
Registriert: 06.05.2004, 17:11

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

Beitrag 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.
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

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

Beitrag 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 :)
Zuletzt geändert von Krishty am 22.12.2009, 19:17, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Schrompf
Moderator
Beiträge: 5045
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

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

Beitrag 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.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

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

Beitrag 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.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
FredK
Beiträge: 31
Registriert: 06.05.2004, 17:11

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

Beitrag 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.
Antworten