Referenz zeigt ins Nirvana
-
Hallo zusammen,
ich habe folgende Konstruktion:
Ein Cluster C, welcher eine Menge von Peers (p1 ... pn) beinhaltet. Jeder Peer hat einen Pointer auf einen ClusterReferrer cRef, welcher ihm erlaubt, den Cluster zu befragen, zu dem er gehört. Der cRef ist innerhalb von C beheimatet. Ein Peer wird innerhalb von C in einer PeerListe verwaltet (letztlich std::vector).
class C{ ... private: ClusterReferrer cRef; PeerList pList; }class Peer { public: void setCurrentCluster(ClusterReferrer * currCluster); ClusterReferrer* getCurrentClusterReferrer() const; private: ClusterReferrer * currCluster; }class ClusterReferrer { public: ClusterReferrer(Cluster & cluster); void setCluster(Cluster & c); Cluster & getCluster(); ClusterID getClusterID() const; private: Cluster & cluster; }Der Construktor von Cluster macht unter anderem:
Cluster::Cluster(ClusterID cId, GroupReferrer * gRef):cRef(*this) { ... }Wenn ich dann aber in einer beliebigen Methode nach dem anlegen des Clusters auf cRef zugreife, zeigt dieser ins Nirvana. Wenn ich die Zwischenstufe des ClusterReferrers raus nehme und direkt ein Pointer auf einen Cluster innerhalb des Peers speichere, dann funktioniert die Sache. Was mach ich falsch?
Vielen Dank!
-
Und was ist nun ein Cluster? Das was im ersten Codestück C ist?
Und was meinst du mit "zeigt ins Nirvana"? Ich sehe da gar keinen Zeiger. Was passiert überhaupt?
Sehr verwirrend das alles.
Zeig am besten mal ein Beispiel.
-
CSpille wettet 5A$ auf: Referenz zeigt auf zerstörtes Stack-Objekt

-
Hi SeppJ,
also ein Cluster ist sozusagen verantwortlich für die Verwaltung von einer Reihe von Peers, als C abgekürzt.
Es passiert folgendes, hier mal im groben Ablauf dargestellt:
Cluster c = createCluster();
c.getID(); // --> ID = 0
c.addPeer(0);
c.getPeer(0).getClusterID(); // --> ID = -123123231
c.getClusterID(); // --> ID = 0Die Indirektion über den ClusterReferrer ist eingefügt, damit sich zum Beispiel ein Peer nicht selbst aus dem Cluster entfernen kann. Daher soll er nur einen beschränkten Zugriff auf Infos von Cluster haben. Wie sich die Referenz auf dem Cluster im ClusterReferrer ändern kann versteh ich auch nicht. Ich benutze gerade Referenzen um NullPointer u.ä. zu vermeiden.

-
hmmm....
Da kann ich mich wohl von meinem Geld verabschieden...
Sieht nach nicht implementierter operator=() aus, oder?
-
Das hier:
uwerothfeld schrieb:
[...]
Cluster::Cluster(ClusterID cId, GroupReferrer * gRef):cRef(*this) { ... }[...]
kann schief gehen, je nachdem, was cRef mit dem übergebenen Objekt so treibt.
thisist an der Stelle, an der Du es benutzt noch gar nicht vollständig konstruiert (du bist ja noch im Ctor). Das führt dazu, dass cRef u.U. auf irgendwelchem uninitialisierten Zeugs rumhobelt.
Eigentlich sollte Dich Dein Compiler da auch warnen.
-
Mh gute Frage,
also ich habe im Cluster nen operator=, das gleiche gilt für Peer und ClusterReferrer. Wo sollte ich da noch ein operator= definieren?
Tachyon schrieb:
Das hier:
uwerothfeld schrieb:
[...]
Cluster::Cluster(ClusterID cId, GroupReferrer * gRef):cRef(*this) { ... }[...]
kann schief gehen, je nachdem, was cRef mit dem übergebenen Objekt so treibt.
thisist an der Stelle, an der Du es benutzt noch gar nicht vollständig konstruiert (du bist ja noch im Ctor). Das führt dazu, dass cRef u.U. auf irgendwelchem uninitialisierten Zeugs rumhobelt.
Eigentlich sollte Dich Dein Compiler da auch warnen.Und wie behebe ich dies? Doch zurück zu Pointern?
-
uwerothfeld schrieb:
Ich benutze gerade Referenzen um NullPointer u.ä. zu vermeiden.
Referenzen sind nicht einfach Zeiger ohne Möglichkeit den Wert Null zu haben. Einfach pauschal Referenzen zu verwenden, nur um die Möglichkeit von Nullzeiger zu verhindern, ist definitiv der falsche Weg und nicht das, wofür Referenzen gedacht sind.
Übrigens hast du immer noch nicht erklärt, was nun der Typ
Clusterin deinem Code darstellt. Du hast einen TypCund einen TypCluster. Oder ist das ein Schreibfehler von deiner Seite und beide Typen sind die gleichen?
Und wie sehen deineoperator=denn aus?Grüssli
-
Dravere schrieb:
Und wie sehen deine
operator=denn aus?Genau...
Kopierst du auch alle Objekte, auf die im Objekt verwiesen wird und im
Destruktor gelöscht werden?
-
Hi,
ja Cluster ist gleich C! Sorry. Also hier nochmal meine operator= für die einzelnen Teilnehmer:
Klasse Cluster:Cluster & Cluster::operator=(const Cluster &rhs){ peerList = rhs.peerList; clusterId = rhs.clusterId; cRef = rhs.cRef; groupReferrer = rhs.groupReferrer; masterReferrer = rhs.masterReferrer; return *this; }//End operator=Klasse Peer:
Peer & Peer::operator=(const Peer &rhs) { peerId = rhs.peerId; role = rhs.role; ta = rhs.ta; state = rhs.state; currCluster = rhs.currCluster; return *this; }//End operator=Klasse ClusterReferrer:
ClusterReferrer & ClusterReferrer::operator = (const ClusterReferrer &rhs){ cluster = rhs.cluster; return *this; }//End operator=
-
uwerothfeld schrieb:
[...]Und wie behebe ich dies? Doch zurück zu Pointern?
Zum Beispiel, ja:
Cluster::Cluster(ClusterID cId, GroupReferrer * gRef) : //alles initialisieren { //weiter initialisieren, sofern in Initliste nicht moeglich cRef.reset(new ClusterReferrer(*this)); //std::tr1::scoped_ptr<ClusterReferrer> }
-
Achso: Zeig mal den Ctor von
ClusterReferrer.
-
Wird
ClusterReferrer * currCluster;im Destruktor gelöscht?
-
Hallo,
was meinst du damit:Cluster::Cluster(ClusterID cId, GroupReferrer * gRef) : //alles initialisieren { //weiter initialisieren, sofern in Initliste nicht moeglich cRef.reset(new ClusterReferrer(*this)); //std::tr1::scoped_ptr<ClusterReferrer> }[/quote]
Boost kann ich leider nicht verwenden. Ist reset sowas wie:void ClusterReferrer::reset(ClusterReferrer * a){ this = a; }???
der Constructor von ClusterReferrer sieht jetzt so aus:
ClusterReferrer::ClusterReferrer(Cluster * c):cluster(c){ }//End ClusterReferrerder von Cluster so:
Cluster::Cluster(ClusterID cId, GroupReferrer * gRef):clusterId(cId), groupReferrer(0), masterReferrer(0), clusterReferrer(this) { std::cout<<"### CONSTRUCTOR: cluster ref daten für cluster "<<clusterId<<": "<<clusterReferrer.getClusterID()<<std::endl; //gibt das richtige aus, komischer weise }//End ClusterDen Peer füge ich hinzu über:
void Cluster::addPeer(Peer & peer) { //setup peer //@bug std::cout<<"### ADD PEER: cluster ref daten für cluster "<<clusterId<<": "<<clusterReferrer.getClusterID()<<std::endl; //hier ist es falsch peer.setCurrentCluster(&clusterReferrer); std::cout<<"id lokal :"<<this->clusterId<<" peer cluster ID "<< peer.getClusterID()<<std::endl; .... }Der Fehler ist bestimmt billig. Aber wie billig genau?
CSpille schrieb:
Wird
ClusterReferrer * currCluster;im Destruktor gelöscht?
Beim Peer? Nein, da es ja innerhalb von Cluster als Member liegt, als nicht als Heap-Objekt. Ist dies falsch?