boost::bind und boost::function Frage.
-
Hi,
kann mir jemand erklären, warum folgender Cope-Schnipsel beim dritten Aufruf von a.call_func erst bei *str und nicht schon bei this einen segmentation fault wirft?
Gruß
typedef boost::function<void (void)> Callback; class A { public: void set_cb_func( Callback cb ) { callback = cb; } void call_func() { callback(); } Callback callback; }; class B { public: B() : str(new std::string) {} ~B() { delete str; } void do_sth() { std::cerr << this << " " << *str << std::endl; *str += "string"; }; std::string * str; }; int main() { A a; { B b; a.set_cb_func(boost::bind(&B::do_sth, &b)); a.call_func(); a.call_func(); } a.call_func(); return 0; }
-
Weils undefiniert ist. Es ist mehr oder weniger Zufall, was passiert. Im schlimmsten Fall passiert beim Testen gar nichts, und man merkt es nicht. Im besten Fall knallt es frühzeitig, so wie bei Dir.
Wieso legst Du den string mit new an? Kommst Du von Java?
-
Weil es UD ist.
-
theta schrieb:
Weil es UD ist.
UD? - Meinst du nicht UB? (undefined behaviour)
-
Tachyon schrieb:
Wieso legst Du den string mit new an? Kommst Du von Java?
Einfach aus Spaß. Hatte wirklich mal keinen Grund. Normalerweise würde ich das nicht machen.
Bei den Tests läuft es immer genau bis "*str". Ich kann den this-Zeiger auch noch dereferenzieren (anstelle "<< this <<" einfach "<< &*this <<" ). Das wundert mich ein wenig.
Die Frage ist jetzt, inwiefern ich mich dagegen absichern kann, dass das Objekt, dem die Member-Funktion gehört, aufhört zu existieren.
-
ehm, doch..
-
class A { public: void f() { } }; int main() { A a; a.f(); }
Du kannst Dir folgendes vorstellen, dein Kompiler setz obigen Code so um:
class A { }; void f(A* a) { } int main() { A a; f(&a); // wobei dann &a eben this ist. }
Wenn jetzt innerhalb von f() nicht auf this oder andere Member zugegriffen wird, "passiert" nichts schlimmes. Dennoch bleibt es UB!
Edit
Die Frage ist jetzt, inwiefern ich mich dagegen absichern kann, dass das Objekt, dem die Member-Funktion gehört, aufhört zu existieren.
Kannst Du nicht. Du musst es wissen, und dafür sorgen, dass das Objekt gültig bleibt, solange es gebraucht wird.