[shared_ptr] deleter that destroys shared_ptr - is it safe?
Hello, Is the following code legal and safe - a) according to the shared_ptr specs b) with the current boost::shared_ptr implementation Thanks! struct a { a() : p_(this, mem_fn(&a::delete_me)) {} void reset() { p_.reset(); } void delete_me() { delete this; } shared_ptr<a> p_; }; int main() { a* p = new a; p->reset(); }
Igor R wrote:
Hello,
Is the following code legal and safe - a) according to the shared_ptr specs
I think so. There is nothing in the specs that prohibits it.
b) with the current boost::shared_ptr implementation
It should be fine. shared_ptr_test contains a similar test case: namespace n_report_1 { class foo { public: foo(): m_self(this) { } void suicide() { m_self.reset(); } private: boost::shared_ptr<foo> m_self; }; void test() { foo * foo_ptr = new foo; foo_ptr->suicide(); } } // namespace n_report_1
struct a { a() : p_(this, mem_fn(&a::delete_me)) {} void reset() { p_.reset(); } void delete_me() { delete this; }
shared_ptr<a> p_; };
int main() { a* p = new a; p->reset(); }
Am Tuesday 08 September 2009 23:28:21 schrieb Igor R:
Hello,
Is the following code legal and safe - a) according to the shared_ptr specs b) with the current boost::shared_ptr implementation
it is, because shared_ptr::reset() is specified to be equivalent to shared_ptr().swap(*this). so the contents of a::p_ are first swap()ed to a temporary and then p is deleted when the temporary goes out of scope, with a::p_ being empty. however, be careful that you leave it at reset() and don't change it to an assignment. p_=shared_ptr<a>(); is NOT safe and is not equivalent to p_.reset() in this case. the assignment in fact produces a invalid write with the current implementation.
Thanks!
struct a { a() : p_(this, mem_fn(&a::delete_me)) {} void reset() { p_.reset(); } void delete_me() { delete this; }
shared_ptr<a> p_; };
int main() { a* p = new a; p->reset(); }
Peter, Stefan, thanks for your clarifications. My question arose from the sad fact that MSVC9.0SP1 doesn't implement tr1::shared_ptr to be safe for the above scenario. So I try to figure out whether it's a bug or legetimate implementation.
it is, because shared_ptr::reset() is specified to be equivalent to shared_ptr().swap(*this).
I found this statement in the boost doc, but does it appear in the Standard, or is it boost-specific? Thanks again.
Well, I found the relevant info in the standard: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf 2.2.3.4 So the MSVC implementation should be considered as a bug.
Stefan Strasser wrote:
Am Tuesday 08 September 2009 23:28:21 schrieb Igor R:
Hello,
Is the following code legal and safe - a) according to the shared_ptr specs b) with the current boost::shared_ptr implementation
it is, because shared_ptr::reset() is specified to be equivalent to shared_ptr().swap(*this). so the contents of a::p_ are first swap()ed to a temporary and then p is deleted when the temporary goes out of scope, with a::p_ being empty.
however, be careful that you leave it at reset() and don't change it to an assignment. p_=shared_ptr<a>(); is NOT safe and is not equivalent to p_.reset() in this case. the assignment in fact produces a invalid write with the current implementation.
This was fixed in 1.39, if I'm not mistaken (see revision 51643). Are you sure that it fails with the current implementation?
participants (3)
-
Igor R
-
Peter Dimov
-
Stefan Strasser