Auf Member eines zerstörten Objektes zugreifen funktioniert
-
Hi!
Ich glaub ich hab sie nicht mehr alle.
void CheckBounceFrameListener::remove(SceneObject ch) { auto vecPos = std::find(sceneObjects.begin(), sceneObjects.end(), ch); if(vecPos != sceneObjects.end()) Singleton.sceneObjects.erase(vecPos); delete ch.mRigidBody; // <<- Hier ch.mRigidBody->getSceneNode()->getParentSceneNode()->removeAndDestroyChild(ch.mRigidBody->getSceneNode()->getName());// <<- Und da }Man beachte Zeile 9 und 10.
Komischerweise funktioniert das Problemlos, glaube ich zumindest...
Wenn ich die beiden Zeilen vertausche, also zuerst greife ich auf den Member zu und zerstöre dann das Objekt, funktioniert es nicht! Oben wird also zuerstch.mRigidBodyzerstört, anschließend greife ich auf eine Funktion zu, die auf eine Membervariable zugreift - was ja mit dem ungültigenthisPointer theoretisch nur schiefgehen kann
Wie kann das angehen?
(Für mehr Code bitte einfach nachfragen)
MfG
P. S.: Ich übergebe keine Referenz, weil SceneObject nur zwei Pointer als Member hat, also so groß wie ein
longsein dürte... :d
-
Was heißt "funktioniert nicht"!?
-
Hacker schrieb:
void CheckBounceFrameListener::remove(SceneObject ch) { auto vecPos = std::find(sceneObjects.begin(), sceneObjects.end(), ch); if(vecPos != sceneObjects.end()) Singleton.sceneObjects.erase(vecPos); delete ch.mRigidBody; // <<- Hier ch.mRigidBody->getSceneNode()->getParentSceneNode()->removeAndDestroyChild(ch.mRigidBody->getSceneNode()->getName());// <<- Und da }Komischerweise funktioniert das Problemlos.
Nur weil man einen Speicher freigibt, heißt das nicht, dass er 1ms später sofort von irgendwas anderem komplett überschrieben wird.
Hacker schrieb:
Wenn ich die beiden Zeilen vertausche, also zuerst greife ich auf den Member zu und zerstöre dann das Objekt, funktioniert es nicht!
Ohne kompilierbares Beispiel kann ich das jetzt nicht nachvollziehen/nachprüfen.
-
Funktioniert nicht heißt, Absturz, der sogar einen Kaltstart erfordern kann.
Natürlich kann ich kein kompilierbares Beispiel vorführen, aber dots Antwort war eigentlich schon perfekt. Es kann gut sein, dass im Destruktor von mRigidBody auf einen Member wie die Scenenode zugegriffen werden kann, also darf es davor nicht zerstört werden. Wenn aber der Speicher gültig bleibt...Lösung: Davor Zeiger auf Scenenode (die btw. unabhängig von meinem zu zerstörenden
mRigidBodyexistiert) nehmen, zerstören und anschließend mit Zeiger arbeiten.Danke für die Hilfe

-
so:
Ogre::SceneNode* scnptr = ch.mRigidBody->getSceneNode(); delete ch.mRigidBody; scnptr->getParentSceneNode()->removeAndDestroyChild(scnptr->getName());Funktioniert, dürfte immer funktionieren.
-
*snip*
-
if(vecPos != sceneObjects.end()) Singleton.sceneObjects.erase(vecPos);Die Abfrage ist nicht nötig.
Singletons sind Mist.
Singleton.sceneObjectsist dasselbe Objekt wie einfachsceneObjects?delete ch.mRigidBody; // <<- Hierdeletebenutzt man nicht.
Wie kommst du eigentlich auf die Idee, eine Ressource einer fremden Klasse zu löschen?Hacker schrieb:
P. S.: Ich übergebe keine Referenz, weil SceneObject nur zwei Pointer als Member hat, also so groß wie ein
longsein dürte... :dSeltsame Rechnung:
sizeof(void *)= 8
sizeof(long)= 8
2 * 8 != 8
-
1. Ja, da hab ich mich mit den Pointergrößen verrechnet. Übrigens ist bei meinem Compiler ein Zeiger 4 Bytes groß, ich kompiliere mit einem 32-Bit MinGW.

2.Wie kommst du eigentlich auf die Idee, eine Ressource einer fremden Klasse zu löschen?
Wie kommst du darauf dass das eine fremde Klasse ist? Es ist eine von mir erstellte Datenstruktur, die wegen Punkt 4 nicht selber Speicher freigeben darf

3. Die Funktion dessen Code ich gezeigt habe ist keine Memberfunktion der Klasse des Singletons. Überhaupt: Singletons sind Mist ist keine Aussage. Ich finde, es ist ein sinnvolles Designpattern, und Designkritiken wollte ich auch gar nicht.

4. Ich kann
deleteso benutzen wie ich will. Ich muss selbst über die Lebenszeiten der Objekte entscheiden, weil sie sich sonst in die Quere kommen.
Also gehen weder Smart-Pointer noch Boosts Pointer-Container. Aber da bin ich mir nicht sicher, ich muss immer an refactoring denken.
-
der code ist ja schrecklich
-
Hacker schrieb:
3. Die Funktion dessen Code ich gezeigt habe ist keine Memberfunktion der Klasse des Singletons. Überhaupt: Singletons sind Mist ist keine Aussage. Ich finde, es ist ein sinnvolles Designpattern, und Designkritiken wollte ich auch gar nicht.

Singleton ist eine Krankheit und kein Designpattern. Insbesodnere gilt es als Paradebeispiel eines Antipatterns.
-
auto vecPos = std::find(sceneObjects.begin(), sceneObjects.end(), ch); if(vecPos != sceneObjects.end()) Singleton.sceneObjects.erase(vecPos);Klar, das ist hässlich.
std::remove(sceneObjects.begin(), sceneObjects.end(), ch);Ich refactore gerade alles auf
std::unique_ptr.
-
Edit: lol. Der obige Code ist peinlich falsch...
Shame on me.
-
So, bin fertig. Und das Ergebnis des refactoring ist mehr als befriedigend: viele Zeilen Code verloren, die Klasse
SceneObjectbrauche ich gar nicht mehr, und die Speicherfreigabe ist jetzt sicher mit einem Pointer Container und ein oder zweiunique_ptrs.Danke!

Ich werde mich das nächste mal ohrfeigen, wenn ich wiederdeletein meinem Code schreibe .