Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r51643 - in trunk: boost/smart_ptr libs/smart_ptr/test
From: pdimov_at_[hidden]
Date: 2009-03-07 17:21:57


Author: pdimov
Date: 2009-03-07 17:21:56 EST (Sat, 07 Mar 2009)
New Revision: 51643
URL: http://svn.boost.org/trac/boost/changeset/51643

Log:
De-optimize assignment into this_type(r).swap(*this) - turns out that they were not equivalent, leading to leaks in contrived cases. Refs #2813.
Added:
   trunk/libs/smart_ptr/test/sp_recursive_assign2_rv_test.cpp (contents, props changed)
   trunk/libs/smart_ptr/test/sp_recursive_assign2_test.cpp (contents, props changed)
   trunk/libs/smart_ptr/test/sp_recursive_assign_rv_test.cpp (contents, props changed)
   trunk/libs/smart_ptr/test/sp_recursive_assign_test.cpp (contents, props changed)
Text files modified:
   trunk/boost/smart_ptr/shared_ptr.hpp | 27 +++++++++++----------------
   trunk/libs/smart_ptr/test/Jamfile.v2 | 4 ++++
   2 files changed, 15 insertions(+), 16 deletions(-)

Modified: trunk/boost/smart_ptr/shared_ptr.hpp
==============================================================================
--- trunk/boost/smart_ptr/shared_ptr.hpp (original)
+++ trunk/boost/smart_ptr/shared_ptr.hpp 2009-03-07 17:21:56 EST (Sat, 07 Mar 2009)
@@ -198,19 +198,7 @@
         boost::detail::sp_enable_shared_from_this( this, p, p );
     }
 
-// generated copy constructor, assignment, destructor are fine...
-
-// except that Borland C++ has a bug, and g++ with -Wsynth warns
-#if defined(__BORLANDC__) || defined(__GNUC__)
-
- shared_ptr & operator=(shared_ptr const & r) // never throws
- {
- px = r.px;
- pn = r.pn; // shared_count::op= doesn't throw
- return *this;
- }
-
-#endif
+// generated copy constructor, destructor are fine
 
     template<class Y>
     explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
@@ -301,13 +289,20 @@
 
 #endif // BOOST_NO_AUTO_PTR
 
-#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
+ // assignment
+
+ shared_ptr & operator=( shared_ptr const & r ) // never throws
+ {
+ this_type(r).swap(*this);
+ return *this;
+ }
+
+#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
 
     template<class Y>
     shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
     {
- px = r.px;
- pn = r.pn; // shared_count::op= doesn't throw
+ this_type(r).swap(*this);
         return *this;
     }
 

Modified: trunk/libs/smart_ptr/test/Jamfile.v2
==============================================================================
--- trunk/libs/smart_ptr/test/Jamfile.v2 (original)
+++ trunk/libs/smart_ptr/test/Jamfile.v2 2009-03-07 17:21:56 EST (Sat, 07 Mar 2009)
@@ -52,5 +52,9 @@
           [ run esft_second_ptr_test.cpp ]
           [ run make_shared_esft_test.cpp ]
           [ run allocate_shared_esft_test.cpp ]
+ [ run sp_recursive_assign_test.cpp ]
+ [ run sp_recursive_assign2_test.cpp ]
+ [ run sp_recursive_assign_rv_test.cpp ]
+ [ run sp_recursive_assign2_rv_test.cpp ]
         ;
 }

Added: trunk/libs/smart_ptr/test/sp_recursive_assign2_rv_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/smart_ptr/test/sp_recursive_assign2_rv_test.cpp 2009-03-07 17:21:56 EST (Sat, 07 Mar 2009)
@@ -0,0 +1,114 @@
+//
+// sp_recursive_assign2_rv_test.cpp
+//
+// Copyright 2009 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X
+{
+public:
+
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const& );
+};
+
+int X::instances = 0;
+
+class Y
+{
+public:
+
+ static int instances;
+
+ Y()
+ {
+ ++instances;
+ }
+
+ ~Y()
+ {
+ --instances;
+ }
+
+private:
+
+ Y( Y const& );
+};
+
+int Y::instances = 0;
+
+static boost::shared_ptr<void> s_pv;
+
+class Z
+{
+public:
+
+ static int instances;
+
+ Z()
+ {
+ ++instances;
+ }
+
+ ~Z()
+ {
+ --instances;
+ s_pv = boost::shared_ptr<Y>( new Y );
+ }
+
+private:
+
+ Z( Z const& );
+};
+
+int Z::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ s_pv = boost::shared_ptr<Z>( new Z );
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 1 );
+
+ s_pv = boost::shared_ptr<X>( new X );
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 1 );
+ BOOST_TEST( Z::instances == 0 );
+
+ s_pv = boost::shared_ptr<Y>();
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ return boost::report_errors();
+}

Added: trunk/libs/smart_ptr/test/sp_recursive_assign2_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/smart_ptr/test/sp_recursive_assign2_test.cpp 2009-03-07 17:21:56 EST (Sat, 07 Mar 2009)
@@ -0,0 +1,122 @@
+//
+// sp_recursive_assign2_test.cpp
+//
+// Copyright 2009 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X
+{
+public:
+
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const& );
+};
+
+int X::instances = 0;
+
+class Y
+{
+public:
+
+ static int instances;
+
+ Y()
+ {
+ ++instances;
+ }
+
+ ~Y()
+ {
+ --instances;
+ }
+
+private:
+
+ Y( Y const& );
+};
+
+int Y::instances = 0;
+
+static boost::shared_ptr<void> s_pv;
+
+class Z
+{
+public:
+
+ static int instances;
+
+ Z()
+ {
+ ++instances;
+ }
+
+ ~Z()
+ {
+ --instances;
+
+ boost::shared_ptr<Y> pv( new Y );
+ s_pv = pv;
+ }
+
+private:
+
+ Z( Z const& );
+};
+
+int Z::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ {
+ boost::shared_ptr<Z> pv( new Z );
+ s_pv = pv;
+ }
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 1 );
+
+ {
+ boost::shared_ptr<X> pv( new X );
+ s_pv = pv;
+ }
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 1 );
+ BOOST_TEST( Z::instances == 0 );
+
+ s_pv.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ return boost::report_errors();
+}

Added: trunk/libs/smart_ptr/test/sp_recursive_assign_rv_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/smart_ptr/test/sp_recursive_assign_rv_test.cpp 2009-03-07 17:21:56 EST (Sat, 07 Mar 2009)
@@ -0,0 +1,114 @@
+//
+// sp_recursive_assign_rv_test.cpp
+//
+// Copyright 2009 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X
+{
+public:
+
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const& );
+};
+
+int X::instances = 0;
+
+class Y
+{
+public:
+
+ static int instances;
+
+ Y()
+ {
+ ++instances;
+ }
+
+ ~Y()
+ {
+ --instances;
+ }
+
+private:
+
+ Y( Y const& );
+};
+
+int Y::instances = 0;
+
+static boost::shared_ptr<void> s_pv;
+
+class Z
+{
+public:
+
+ static int instances;
+
+ Z()
+ {
+ ++instances;
+ }
+
+ ~Z()
+ {
+ --instances;
+ s_pv = boost::shared_ptr<void>( new Y );
+ }
+
+private:
+
+ Z( Z const& );
+};
+
+int Z::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ s_pv = boost::shared_ptr<void>( new Z );
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 1 );
+
+ s_pv = boost::shared_ptr<void>( new X );
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 1 );
+ BOOST_TEST( Z::instances == 0 );
+
+ s_pv = boost::shared_ptr<void>();
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ return boost::report_errors();
+}

Added: trunk/libs/smart_ptr/test/sp_recursive_assign_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/smart_ptr/test/sp_recursive_assign_test.cpp 2009-03-07 17:21:56 EST (Sat, 07 Mar 2009)
@@ -0,0 +1,122 @@
+//
+// sp_recursive_assign_test.cpp
+//
+// Copyright 2009 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X
+{
+public:
+
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const& );
+};
+
+int X::instances = 0;
+
+class Y
+{
+public:
+
+ static int instances;
+
+ Y()
+ {
+ ++instances;
+ }
+
+ ~Y()
+ {
+ --instances;
+ }
+
+private:
+
+ Y( Y const& );
+};
+
+int Y::instances = 0;
+
+static boost::shared_ptr<void> s_pv;
+
+class Z
+{
+public:
+
+ static int instances;
+
+ Z()
+ {
+ ++instances;
+ }
+
+ ~Z()
+ {
+ --instances;
+
+ boost::shared_ptr<void> pv( new Y );
+ s_pv = pv;
+ }
+
+private:
+
+ Z( Z const& );
+};
+
+int Z::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ {
+ boost::shared_ptr<void> pv( new Z );
+ s_pv = pv;
+ }
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 1 );
+
+ {
+ boost::shared_ptr<void> pv( new X );
+ s_pv = pv;
+ }
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 1 );
+ BOOST_TEST( Z::instances == 0 );
+
+ s_pv.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ return boost::report_errors();
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk