diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index 4b3dcde3a..9b3e84fb0 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -354,16 +354,20 @@ template inline void destruct_elements_of_array(T *ptr, size_t size) template inline T* construct_elements_of_array(T *ptr, size_t size) { size_t i; +#ifdef EIGEN_EXCEPTIONS try +#endif { for (i = 0; i < size; ++i) ::new (ptr + i) T; return ptr; } +#ifdef EIGEN_EXCEPTIONS catch (...) { destruct_elements_of_array(ptr, i); throw; } +#endif } /***************************************************************************** @@ -385,30 +389,38 @@ template inline T* aligned_new(size_t size) { check_size_for_overflow(size); T *result = reinterpret_cast(aligned_malloc(sizeof(T)*size)); +#ifdef EIGEN_EXCEPTIONS try +#endif { return construct_elements_of_array(result, size); } +#ifdef EIGEN_EXCEPTIONS catch (...) { aligned_free(result); throw; } +#endif } template inline T* conditional_aligned_new(size_t size) { check_size_for_overflow(size); T *result = reinterpret_cast(conditional_aligned_malloc(sizeof(T)*size)); +#ifdef EIGEN_EXCEPTIONS try +#endif { return construct_elements_of_array(result, size); } +#ifdef EIGEN_EXCEPTIONS catch (...) { conditional_aligned_free(result); throw; } +#endif } /** \internal Deletes objects constructed with aligned_new @@ -438,15 +450,19 @@ template inline T* conditional_aligned_realloc_new(T* pt T *result = reinterpret_cast(conditional_aligned_realloc(reinterpret_cast(pts), sizeof(T)*new_size, sizeof(T)*old_size)); if(new_size > old_size) { +#ifdef EIGEN_EXCEPTIONS try +#endif { construct_elements_of_array(result+old_size, new_size-old_size); } +#ifdef EIGEN_EXCEPTIONS catch (...) { conditional_aligned_free(result); throw; } +#endif } return result; } @@ -458,15 +474,19 @@ template inline T* conditional_aligned_new_auto(size_t s T *result = reinterpret_cast(conditional_aligned_malloc(sizeof(T)*size)); if(NumTraits::RequireInitialization) { +#ifdef EIGEN_EXCEPTIONS try +#endif { construct_elements_of_array(result, size); } +#ifdef EIGEN_EXCEPTIONS catch (...) { conditional_aligned_free(result); throw; } +#endif } return result; } @@ -480,15 +500,19 @@ template inline T* conditional_aligned_realloc_new_auto( T *result = reinterpret_cast(conditional_aligned_realloc(reinterpret_cast(pts), sizeof(T)*new_size, sizeof(T)*old_size)); if(NumTraits::RequireInitialization && (new_size > old_size)) { +#ifdef EIGEN_EXCEPTIONS try +#endif { construct_elements_of_array(result+old_size, new_size-old_size); } +#ifdef EIGEN_EXCEPTIONS catch (...) { conditional_aligned_free(result); throw; } +#endif } return result; } diff --git a/test/ctorleak.cpp b/test/ctorleak.cpp index 72ab94b66..f3f4411c8 100644 --- a/test/ctorleak.cpp +++ b/test/ctorleak.cpp @@ -4,11 +4,30 @@ struct Foo { + static unsigned object_count; + static unsigned object_limit; int dummy; - Foo() { if (!internal::random(0, 10)) throw Foo::Fail(); } + + Foo() + { +#ifdef EIGEN_EXCEPTIONS + // TODO: Is this the correct way to handle this? + if (Foo::object_count > Foo::object_limit) { throw Foo::Fail(); } +#endif + ++Foo::object_count; + } + + ~Foo() + { + --Foo::object_count; + } + class Fail : public std::exception {}; }; +unsigned Foo::object_count = 0; +unsigned Foo::object_limit = 0; + namespace Eigen { template<> @@ -34,10 +53,17 @@ namespace Eigen void test_ctorleak() { + Foo::object_count = 0; + Foo::object_limit = internal::random(0, 14 * 92 - 2); +#ifdef EIGEN_EXCEPTIONS try +#endif { Matrix m(14, 92); eigen_assert(false); // not reached } +#ifdef EIGEN_EXCEPTIONS catch (const Foo::Fail&) { /* ignore */ } +#endif + VERIFY_IS_EQUAL(static_cast(0), Foo::object_count); }