boost::shared_ptr nicht vectorfähig?
-
hi leute
ich hab folgendes problem
ich hab einen vector voll boost::shared_pointer auf eine klasse
ich fülle den vector mit quasi dem nullpendant der klasse
danach wird der vector bei bedarf mit derivaten dieser klasse überschrieben (d.h. nur halt das element was gebraucht wird wird von base zu derive)so nun hab ich halt ein element überschrieben, will bei einem anderen (einem der base elemente) eine methode ausführen, klappt auch
dann möchte ich aber eine methode von dem derive ausführen und da hakts
speicherzugriffsverletzungblablaist shared_pointer nicht dafür gebaut mit vererbung umzugehen?!? (kann ich mir nicht vorstellen)
liegt das daran dass der vector intern was kopiert und sharedptr das nicht mag ?!?beim debuggen jedenfalls hängt das genau in der zeile, die position im vector ist richtig (liegt also nichts ausserhalb der vector range), der zeiger von shared ptr ist richtig (da gehts auf jedenfall ohne probleme durch) und dann wenns zur methode gehen sollte krachts
mfg mosho
-
Es wäre besser, code statt umständlicher Worte zu posten.
Eigentlich sollte das was du vorhast klappen. Wobei die boost ptr_container wohl eher anzuraten sind.
-
ok, ich versuch das mal zusammenzufassen
die benutzten klassen
class Base { public: virtual void init() { /* do what... */ } virtual void exit() { /* do what... */ } protected: bool isInit; }; class Derive : public Base { void init() { /* do what... */ } void exit() { /* do what... */ } };
main
int main() { std::vector<boost::shared_ptr<Base>> vec; vec.resize(2); for(int i = 0; i < vec.size(); ++i) vec[i] = boost::shared_ptr<Base>(new Base); vec[0]->init(); // tu was vec[0]->exit(); vec[1] = shared_ptr<Base>(new Derive); vec[1]->init(); // Hier crashts, 1 ist innerhalb der vector range und der zeiger sollte gültig sein... }
-
boost::shared_dynamic_cast<>
-
bei mir "crasht" da nix.
-
Kóyaánasqatsi schrieb:
boost::shared_dynamic_cast<>
Wozu? An seinem gezeigten Code sehe ich jedenfalls kein Grund dafür (Aber ebenso keinen Grund für einen Absturz).
-
std::vector und boost::shared_ptr vertragen sich wunderbar.
und boost::shared_ptr verträgt sich supi mit Vererbung.Dein Problem liegt also vermutlich wo anders. Vielleicht versuchst du ja die Objekte auf die der boost::shared_ptr zeigt einfach nur zugeweisen, wodurch sie "zerschnitten" werden (slicing).
EDIT: übersehen. Nein, tust du nicht. Keine Ahnung wieso das nicht gehen sollte.
EDIT2: step doch einfach mal mit dem Debugger rein.
-
Skym0sh0 schrieb:
class Base { public: virtual void init() { /* do what... */ } virtual void exit() { /* do what... */ } protected: bool isInit; }; class Derive : public Base { void init() { /* do what... */ } void exit() { /* do what... */ } };
Wenn Du nach einer Übersetzung von "Tu was" suchst, dann würde das "Do something" heißen.
Ich bemerke, dass Base keinen virtuellen Destruktor hat.
Skym0sh0 schrieb:
int main() { std::vector<boost::shared_ptr<Base>> vec; vec.resize(2); for(int i = 0; i < vec.size(); ++i) vec[i] = boost::shared_ptr<Base>(new Base); vec[0]->init(); // tu was vec[0]->exit(); vec[1] = shared_ptr<Base>(new Derive); vec[1]->init(); // Hier crashts, 1 ist innerhalb der vector range und der zeiger sollte gültig sein... }
Zeile 3 des letzten Teils enthält ein ">>" was ein "> >" sein sollte, damit es auch andere Compiler im C++98-Modus fressen. Ohne das Leerzeichen ist das erst gültig ab C++0x, da es sonst als Verschiebe-Operator interpretiert wird.
Und
vec[1] = shared_ptr<Base>(new Derive);
kann man auch kürzer schreiben:
vec[1].reset(new Derive);
Obwohl Base keinen virtuellen Destruktor hat, ist dies in diesem Fall ausnahmsweise legal. shared_ptr verwendet
template
isierte Konstruktoren und reset-Funktionen, so dass der ZeigertypDerived*
erkannt wird. Folgendes funktioniert aber schon nicht mehr richtig (undefined behaviour)
`Base* ptr = new Derive;
vec[1].reset(ptr);
`
da ptr vom Typ Base* ist, Base keinen virtuellen Destruktor hat und daher shared_ptr nicht den richtigen Destruktor aufrufen kann. Also, wenn Du Objekte polymorpher Klassen dynamisch anlegen und löschen willst, sollte der Destruktor der Basisklasse virtuell sein.Sonst gibt es nicht viel auszusetzen. Du musst irgendwas anderes falsch gemacht haben; denn das Programm ist kompilierbar und lauffähig.
kk
-
folgendes hab ich verändert
int main() { std::vector<boost::shared_ptr<Base>> vec; vec.resize(2); for(int i = 0; i < vec.size(); ++i) vec[i] = boost::shared_ptr<Base>(new Base); vec[0]->init(); // tu was vec[0]->exit(); Base * d = new Derive; vec[1].reset(d); // hab reset anstelle dem alten verwendet vec[1]->init(); // crasht }
achja, und ich hatte die ganze zeit nen virtuellen Dtor
hab den nur net hier reingeschrieben gehabt...klappen tuts nicht
(( vorm edit dachte ich hätts geklappt, war aber an der falschen stelle ))klappt immer noch net...
mh die speicheraddresse ist 0x00000004
also eig die zweite int adresse im ram wenn ich das richtig sehe ?!?mh ich hab keinen plan warums net geht
-
achja, und ich hatte die ganze zeit nen virtuellen Dtor
hab den nur net hier reingeschrieben gehabt...Wie willst du den Fehler finden, wenn du nie den original Code postest?
Mal abgesehen davon dass du damit die Zeit anderer Foren-Teilnehmer verschwendest, und das IMO recht unhöflich ist, wirst du auch kaum eine brauchbare Antwort bekommen, wenn du immer irgendwie abgeänderten und/oder unvollständigen Code postest.
-
der original code beläuft sich auf recht viele zeilen, den wollt ihr hier doch auch nicht oder?!?
ich hab den fehler...
ich hab in einigen construtoren ZeroMemory
und das verträgt sich wohl voll nicht mit gewissen sachenhab das jetzt rausgemacht und jetzt klappts
-
Skym0sh0 schrieb:
der original code beläuft sich auf recht viele zeilen, den wollt ihr hier doch auch nicht oder?!?
Nein, aber man kann erwarten dass der Fragesteller versucht, das Problem so weit einzugrenzen, dass es nicht mehr so viel Code ist. Idealerweise hat er mit dem Debugger &Co einzelne Stellen gefunden, bei denen das Problem auftritt. Dann kann er diesen Bereich posten. Dabei sollte aber der Fehler auftreten, was bei dir nicht der Fall war!
ich hab in einigen construtoren ZeroMemory
Und du weißt was ZeroMemory macht?
-
aber ich hab doch den debugger benutzt und auch die ergebnisse geschrieben
ja zeromemory füllt auf assembler ebene (also recht low level) die gesamte grösse der angegeben struktur mit null(en)
hab dabei nur nicht bedacht dass manche sachen einfach werte brauchen
werden dabei eigentlich auch constanten zurückgesetzt?
-
Poste ein kurzes aber vollständiges, kompilierbares Beispiel, welches das Problem enthält. Das erfordert ein Isolieren, Kürzen und Testen Deinerseits. Pseudo-Code runter tippen, von dem Du nur glaubst, dass er den Fehler enthält, führt zu nichts.
Skym0sh0 schrieb:
ja zeromemory füllt auf assembler ebene (also recht low level) die gesamte grösse der angegeben struktur mit null(en)
hab dabei nur nicht bedacht dass manche sachen einfach werte brauchen
werden dabei eigentlich auch constanten zurückgesetzt?
Das klingt schon mal sehr nach undefiniertem Verhalten. Aber was Du da genau machst, wissen wir noch nicht, weil Du es nicht gezeigt hast.
kk