Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r81684 - in trunk: boost/smart_ptr/detail libs/smart_ptr/test
From: glenfe_at_[hidden]
Date: 2012-12-03 00:41:35


Author: glenfe
Date: 2012-12-03 00:41:34 EST (Mon, 03 Dec 2012)
New Revision: 81684
URL: http://svn.boost.org/trac/boost/changeset/81684

Log:
For fixed size arrays upon constructor exception thrown destroy correctly.
Text files modified:
   trunk/boost/smart_ptr/detail/array_deleter.hpp | 106 +++++++++++++++++++++++++++++----------
   trunk/libs/smart_ptr/test/allocate_shared_array_throws_test.cpp | 16 ++++++
   trunk/libs/smart_ptr/test/make_shared_array_throws_test.cpp | 16 ++++++
   3 files changed, 110 insertions(+), 28 deletions(-)

Modified: trunk/boost/smart_ptr/detail/array_deleter.hpp
==============================================================================
--- trunk/boost/smart_ptr/detail/array_deleter.hpp (original)
+++ trunk/boost/smart_ptr/detail/array_deleter.hpp 2012-12-03 00:41:34 EST (Mon, 03 Dec 2012)
@@ -24,13 +24,18 @@
                   object(0) {
             }
             ~array_deleter() {
- destroy();
+ destroy(size);
             }
             void construct(T* memory) {
                 object = memory;
                 for (std::size_t i = 0; i < size; i++) {
- void* p1 = object + i;
- ::new(p1) T();
+ try {
+ void* p1 = memory + i;
+ ::new(p1) T();
+ } catch (...) {
+ destroy(i);
+ throw;
+ }
                 }
             }
 #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
@@ -38,39 +43,59 @@
             void construct(T* memory, Args&&... args) {
                 object = memory;
                 for (std::size_t i = 0; i < size; i++) {
- void* p1 = object + i;
- ::new(p1) T(args...);
+ try {
+ void* p1 = memory + i;
+ ::new(p1) T(args...);
+ } catch (...) {
+ destroy(i);
+ throw;
+ }
                 }
             }
 #endif
             void construct_list(T* memory, const T* list) {
                 object = memory;
                 for (std::size_t i = 0; i < size; i++) {
- void* p1 = object + i;
- ::new(p1) T(list[i]);
+ try {
+ void* p1 = memory + i;
+ ::new(p1) T(list[i]);
+ } catch (...) {
+ destroy(i);
+ throw;
+ }
                 }
             }
             void construct_list(T* memory, const T* list, std::size_t n) {
                 object = memory;
                 for (std::size_t i = 0; i < size; i++) {
- void* p1 = object + i;
- ::new(p1) T(list[i % n]);
+ try {
+ void* p1 = memory + i;
+ ::new(p1) T(list[i % n]);
+ } catch (...) {
+ destroy(i);
+ throw;
+ }
                 }
             }
             void construct_noinit(T* memory) {
                 object = memory;
                 for (std::size_t i = 0; i < size; i++) {
- void* p1 = object + i;
- ::new(p1) T;
+ try {
+ void* p1 = memory + i;
+ ::new(p1) T;
+ } catch (...) {
+ destroy(i);
+ throw;
+ }
                 }
             }
             void operator()(const void*) {
- destroy();
+ destroy(size);
             }
         private:
- void destroy() {
+ void destroy(std::size_t n) {
                 if (object) {
- for (std::size_t i = size; i > 0; ) {
+ for (std::size_t i = n; i > 0; ) {
                         object[--i].~T();
                     }
                     object = 0;
@@ -86,13 +111,18 @@
                 : object(0) {
             }
             ~array_deleter() {
- destroy();
+ destroy(N);
             }
             void construct(T* memory) {
                 object = memory;
                 for (std::size_t i = 0; i < N; i++) {
- void* p1 = object + i;
- ::new(p1) T();
+ try {
+ void* p1 = memory + i;
+ ::new(p1) T();
+ } catch (...) {
+ destroy(i);
+ throw;
+ }
                 }
             }
 #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
@@ -100,39 +130,59 @@
             void construct(T* memory, Args&&... args) {
                 object = memory;
                 for (std::size_t i = 0; i < N; i++) {
- void* p1 = object + i;
- ::new(p1) T(args...);
+ try {
+ void* p1 = memory + i;
+ ::new(p1) T(args...);
+ } catch (...) {
+ destroy(i);
+ throw;
+ }
                 }
             }
 #endif
             void construct_list(T* memory, const T* list) {
                 object = memory;
                 for (std::size_t i = 0; i < N; i++) {
- void* p1 = object + i;
- ::new(p1) T(list[i]);
+ try {
+ void* p1 = memory + i;
+ ::new(p1) T(list[i]);
+ } catch (...) {
+ destroy(i);
+ throw;
+ }
                 }
             }
             void construct_list(T* memory, const T* list, std::size_t n) {
                 object = memory;
                 for (std::size_t i = 0; i < N; i++) {
- void* p1 = object + i;
- ::new(p1) T(list[i % n]);
+ try {
+ void* p1 = memory + i;
+ ::new(p1) T(list[i % n]);
+ } catch (...) {
+ destroy(i);
+ throw;
+ }
                 }
             }
             void construct_noinit(T* memory) {
                 object = memory;
                 for (std::size_t i = 0; i < N; i++) {
- void* p1 = object + i;
- ::new(p1) T;
+ try {
+ void* p1 = memory + i;
+ ::new(p1) T;
+ } catch (...) {
+ destroy(i);
+ throw;
+ }
                 }
             }
             void operator()(const void*) {
- destroy();
+ destroy(N);
             }
         private:
- void destroy() {
+ void destroy(std::size_t n) {
                 if (object) {
- for (std::size_t i = N; i > 0; ) {
+ for (std::size_t i = n; i > 0; ) {
                         object[--i].~T();
                     }
                     object = 0;

Modified: trunk/libs/smart_ptr/test/allocate_shared_array_throws_test.cpp
==============================================================================
--- trunk/libs/smart_ptr/test/allocate_shared_array_throws_test.cpp (original)
+++ trunk/libs/smart_ptr/test/allocate_shared_array_throws_test.cpp 2012-12-03 00:41:34 EST (Mon, 03 Dec 2012)
@@ -43,5 +43,21 @@
     } catch (...) {
         BOOST_TEST(type::instances == 0);
     }
+#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
+ BOOST_TEST(type::instances == 0);
+ try {
+ boost::allocate_shared<type[6]>(std::allocator<type>());
+ BOOST_ERROR("allocate_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ try {
+ boost::allocate_shared<type[3][2]>(std::allocator<type>());
+ BOOST_ERROR("allocate_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+#endif
     return boost::report_errors();
 }

Modified: trunk/libs/smart_ptr/test/make_shared_array_throws_test.cpp
==============================================================================
--- trunk/libs/smart_ptr/test/make_shared_array_throws_test.cpp (original)
+++ trunk/libs/smart_ptr/test/make_shared_array_throws_test.cpp 2012-12-03 00:41:34 EST (Mon, 03 Dec 2012)
@@ -43,6 +43,22 @@
     } catch (...) {
         BOOST_TEST(type::instances == 0);
     }
+#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
+ BOOST_TEST(type::instances == 0);
+ try {
+ boost::make_shared<type[6]>();
+ BOOST_ERROR("make_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ try {
+ boost::make_shared<type[3][2]>();
+ BOOST_ERROR("make_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+#endif
     BOOST_TEST(type::instances == 0);
     try {
         boost::make_shared_noinit<type[]>(6);


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