seltsame Variblenänderungen am Ende von Konstruktoraufruf
-
äh wie jetz? wie kommst du auf 0xFEEEFEEE? Ich hab das auf so einer Seite im Internet umrechnen lassen. Und was würde das dann bedeuten, wenn es freed heap memory wäre?
-
Knobbers schrieb:
@volkard
17891602 entspricht im hexadeziemalsystem 1110112. Das kommt in der Liste nicht vor.Du sollst doch nicht selber umrechnen. In der IDE im Debugger rechte Maustaste auf die Anzeige der Variablen und auf hexadezimale Anzeige umstellen, hatte gehofft, sowas gibt es.
Und per Hand müßtest Du das Vorzeichen beachten. Es ist ja -17891602.
Als rechnest Du http://lmgtfy.com/?q=-17891602+%2B+2^32+to+hex
-
Aber du speicherst nicht zufällig Zeiger auf die Objekte, bevor die in den Vector kommen?
Äh doch mach ich? Hab aber nich ganz verstanden warum sich dann was genau ändern soll.
@volkard:
Achso danke und was sagt mir der Fehler dann, bzw. was hab ich dann falsch gemacht?
btw cooles Programm, lmgtfy^^
-
Knobbers schrieb:
@volkard:
Achso danke und was sagt mir der Fehler dann, bzw. was hab ich dann falsch gemacht?Tja, leider habe ich keine Ahnung. Ich weiß nur, aß mir 0xfeeefeee nicht passiert.
Aber jetzt wissen Knobbers, elise und Caligulaminus, daß auf dem Speicherbereich vermutlich HeapFree() aufgerufen wurde und knacken das Problem. :xmas1:
-
Knobbers schrieb:
äh wie jetz? wie kommst du auf 0xFEEEFEEE? Ich hab das auf so einer Seite im Internet umrechnen lassen. Und was würde das dann bedeuten, wenn es freed heap memory wäre?
guck mal deinen screen genau an...
-
@unskilled
ah ja die Textur wurde auch auf feeefeee gestellt^^
Ok, das passt zum Problem. Was ist zu tun?
-
das du auf speicher zugreifst, der schon frei gegeben wurde...
-
unskilled schrieb:
das du auf speicher zugreifst, der schon frei gegeben wurde...
Und genau das war meine Vermutung

Hier zur Veranschaulichung:#include <iostream> #include <vector> using namespace std; struct Test { bool a, b; int c; Test(bool a, bool b, int c) : a(a), b(b), c(c) {} }; ostream& operator<<(ostream &os, Test const& t) { os << t.a << ' ' << t.b << ' ' << t.c; return os; } void assign_and_append(Test *& tp, bool a, bool b, int c, vector<Test>& tv) { Test t(a, b, c); // temporäres Objekt tv.push_back(t); // Legt eine _Kopie_ von t in den Vektor tp = &t; // Weist dem Zeiger die Adresse des temporären Objektes zu } // Hier wurde t zerstört, tp zeigt auf freigegebenen Speicher! int main() { vector<Test> tv; Test *t1, *t2; assign_and_append(t1, false, true, 12340, tv); t2 = &tv[0]; cout << *t1 << endl << *t2 << endl << tv[0] << endl; }
-
Zu dem Zeitpunkt, an dem der Zeiger auf freigegebenen Speicher zeigt, ist die Instanz des Objektes, auf das er eigentlich zeigen sollte, laut Debugger noch vorhanden!
-
Knobbers schrieb:
Zu dem Zeitpunkt, an dem der Zeiger auf freigegebenen Speicher zeigt, ist die Instanz des Objektes, auf das er eigentlich zeigen sollte, laut Debugger noch vorhanden!
Kein Debugger kann dir sagen, ob an einer bestimmten Speicherstelle ein bestimmtes Objekt existiert oder nicht.
Alles was dir mitgeteilt wird ist: falls an der Stelle ein bestimmtes Objekt existiert, dann hat es den angezeigten Inhalt.
-
Ok, vielen Dank euch allen für eure Hilfe!
Ich werd mal sehn, ob ich meinen Fehler finde.
-
Hi, ich konnte leider den Fehler immer noch nicht finden.
Ich hab jetzt folgenden Versuch gemacht:[code] schlacht::schlacht(...){ (...) //die Adresse einer Instanz der Klasse "einheit" zuweisen test_pointer_auf_einheit = sArmee->getEinheit(0); //die Adresse einer Instanz der Klasse "feld" zuweisen test_pointer_auf_einheit->test_pointer_auf_feld = sMap.getFeld(0,0); //einen bool-Member der Instanz ändern sMap.getFeld(0,0)->belegt = false; } //diese Funktion wird kurz nach dem Konstruktor aufgerufen void schlacht::aktionenJeFrame(){ //einheit-zeiger funktioniert, test1 bekommt den richtigen Wert int test1 = test_pointer_auf_einheit->pos.x; //die Instanz von "feld" existiert noch, test2 wird false bool test2 = sMap.getFeld(0,0)->belegt; // test3 wird true, der Zeiger funktioniert nicht richtig bool test3 = test_pointer_auf_einheit->test_pointer_auf_feld->belegt; weiteren Member am Ende des Zeigers werden von MSVS als FEEEFEEE angezeigtDie Instanz der Feld-Klasse, auf die mein Zeiger zeigt, ist also noch vorhanden (Zeile 20). Und trotzdem kann ich sie nicht über den Zeiger ansteuern, der von meiner Einheit-Instanz gespeichert wird (Zeile 23). Habt ihr noch ein paar Ideen auf Lager? Ich weiß echt nicht mehr weiter.
-
Was machst du im schlacht-Konstruktor vor dem Zuweisen der Zeiger?
Wo kommen sMap/sArmee her?
Die Punkte im Konstruktor machen mich stutzig: Steht das wirklich da? Und wenn nicht: hast du mehrere Konstruktoren und rufst sicher den richtigen auf?
Kannst du nicht einfach dein Projekt in ein zip packen und um Download anbieten? Oder wenigstens ein minimales Beispiel, das man nachvollziehen kann. Mit so mini-Infos kann man nur raten...
-
@Rhododendronsau
Anstelle der Punkte steht einen Haufen Zeug. sMap und sArmee sind Klassen und Member von schlacht. Und ja, der richtige Konstruktor wird aufgerufen, ich debugge mich ja Schritt für Schritt durch die geposteten Zeilen.Der Punkt ist doch, dass ich UNMITTELBAR nach Beenden des Konstruktors nicht über den Zeiger "test_zeiger_auf_feld" auf das gewünschte Feld zugreifen kann (per Debugger oder per Code), OBWOHL das Feld exisitert (Zeile 22) sowie die Einheit, welche diesen Zeiger testhalber speichert (Zeile 19).
Zwischen denn letzten Zeilen des Konstruktors und dem Funktionsaufruf von "aktionenJeFrame" ist sonst kein Code.
-
Was genau liefert denn "sArmee->getEinheit(0)" bzw. "sMap.getFeld(0,0)" zurück?
Zeig mal den Code - ich tippe auf einen Zeiger (Adresse) einer lokalen Variable (peng!)...
-
Th69 schrieb:
Was genau liefert denn "sArmee->getEinheit(0)" bzw. "sMap.getFeld(0,0)" zurück?
Ich versteh nicht. Willst du den Wert wissen? 0x1235ef4c? Adressen halt.
Th69 schrieb:
lokalen Variable
Was soll lokal sein? Das Feld auf das "test_pointer_auf_feld" zeigt? Wenn das so wäre könnte ich ja nicht wie in Zeile 22 meines Codes drauf zugreifen.
-
Knobbers schrieb:
Was soll lokal sein? Das Feld auf das "test_pointer_auf_feld" zeigt? Wenn das so wäre könnte ich ja nicht wie in Zeile 22 meines Codes drauf zugreifen.
Genau, das Feld. Wenn dein sMap() intern ein Array speichert, und du dann sowas machst:
Feld f = Array[0][0]; return &f;Dann liegt in deinem test_pointer eine Adresse auf ein temporäres Objekt-Bumm!
Und darauf zugreifen kannst du natürlich - sowas nennt sich "undefiniertes Verhalten". Es kann gut gehen, aber auch nicht, Du kannst auch plötzlich nackt in der U-Bahn stehen...
Dass die Werte plötzlich nicht mehr stimmen deutet sehr stark auf undefiniertes Verhalten hin...
-
@Siebenweger
Ich mach glaub ich sowas ähnliches, wie du vermutet hast. Ich speicher die Felder in sMap in einem Vektor.
for (int i = 0; i < 100; i++){ for (unsigned int j = 0; j < 100; j++){ felder.push_back(feld(i,j)); //std::vector<feld> felder } }Wenn ich testhalber Felder außerhalb des Vektors anlege und ihre Adresse verteile, dann funktioniert es. Aber wieso funktioniert es nicht mit dem Vektor? Dieser ist ja ein fester sMap-Member. Der dürfte ja nicht einfach plötzlich seinen Inhalt freigeben. Hat das irgendwas mit seiner variablen Größe zu tun oder so?
Siebenweger schrieb:
Du kannst auch plötzlich nackt in der U-Bahn stehen...
Davor hat mich kein C++-Tutorial gewarnt!!!
-
Hallo,
mich hat das Problem auch weiterhin verfolgt. Ich hab jetz ein anschauliches Codebeispiel programmiert:#include <iostream> #include <vector> class A{ public: A(std::vector<int> *Zahlen); A(); std::vector<int> *zahlen; }; A::A(std::vector<int> *Zahlen){ zahlen = Zahlen; } class B{ public: B(); std::vector<int> zahlen; A myA; }; B::B(){ for (int i = 0; i < 100; i++){ zahlen.push_back(i); } myA = A(&zahlen); std::cout << myA.zahlen->at(99) << std::endl; } A::A(){} B myB; int main( int argc, char* args[] ){ myB = B(); myB.zahlen.at(99) = 17; std::cout << myB.zahlen.at(99) << std::endl; //hier kommt der Fehler std::cout << myB.myA.zahlen->at(99) << std::endl; return 0; }Weiß vielleicht jemand, warum das zu einem Fehler führt?
-
Das kann ich dir sagen; es ist aber etwas verworren.
Grundlegend ist dein Denkfehler, dass Klassen in C++ keine Referenztypen wie in Java oder C# sind. Dein Problem sind
myA = A(&zahlen);und
myB = B();- konkret ausgelöst wird der Fehler von letzterem.
myB ist zu diesem Zeitpunkt bereits ein vollständig initialisiertes Objekt vom Typ B, also wird hier kein Konstruktor für myB aufgerufen, sondern ein temporäres Objekt vom Typ B erstellt und dann in B::operator= geworfen. Da du keinen eigenen operator= geschrieben hast, wird der vom Compiler generierte benutzt, und dieser kopiert schlicht die Member des temporären Objektes nach myB, indem er ihre respektiven operator= benutzt.
Da A ebenfalls keinen explizit geschriebenen operator= hat, wird hier ebenfalls der vom Compiler generierte benutzt, und dieser kopiert dann den Zeiger aus dem myA-Objekt im temporären B-Objekt aus main in das myA-Objekt in myB; dieser Zeiger zeigt auf den Vektor im temporären B-Objekt.
Wenn also nach getaner Arbeit das temporäre B-Objekt zerstört wird, zeigt der Zeiger myB.myA.zeiger dorthin, wo einmal der Vektor des temporären Objektes war und jetzt nicht mehr ist. Er ist mithin ungültig, und alle Versuche, durch ihn auf etwas zuzugreifen, erzeugen undefiniertes Verhalten.