Applied changes suggested by Christoph Hertzberg to c'tor leak fix.

- Enclose exception handling in '#ifdef EIGEN_EXCEPTIONS'.
- Use an object counter to demonstrate the bug more readily.
This commit is contained in:
Moritz Klammler 2014-07-18 23:19:56 +02:00
parent 58687aa5e6
commit 529e6cb552
2 changed files with 51 additions and 1 deletions

View File

@ -354,16 +354,20 @@ template<typename T> inline void destruct_elements_of_array(T *ptr, size_t size)
template<typename T> inline T* construct_elements_of_array(T *ptr, size_t size) template<typename T> inline T* construct_elements_of_array(T *ptr, size_t size)
{ {
size_t i; size_t i;
#ifdef EIGEN_EXCEPTIONS
try try
#endif
{ {
for (i = 0; i < size; ++i) ::new (ptr + i) T; for (i = 0; i < size; ++i) ::new (ptr + i) T;
return ptr; return ptr;
} }
#ifdef EIGEN_EXCEPTIONS
catch (...) catch (...)
{ {
destruct_elements_of_array(ptr, i); destruct_elements_of_array(ptr, i);
throw; throw;
} }
#endif
} }
/***************************************************************************** /*****************************************************************************
@ -385,30 +389,38 @@ template<typename T> inline T* aligned_new(size_t size)
{ {
check_size_for_overflow<T>(size); check_size_for_overflow<T>(size);
T *result = reinterpret_cast<T*>(aligned_malloc(sizeof(T)*size)); T *result = reinterpret_cast<T*>(aligned_malloc(sizeof(T)*size));
#ifdef EIGEN_EXCEPTIONS
try try
#endif
{ {
return construct_elements_of_array(result, size); return construct_elements_of_array(result, size);
} }
#ifdef EIGEN_EXCEPTIONS
catch (...) catch (...)
{ {
aligned_free(result); aligned_free(result);
throw; throw;
} }
#endif
} }
template<typename T, bool Align> inline T* conditional_aligned_new(size_t size) template<typename T, bool Align> inline T* conditional_aligned_new(size_t size)
{ {
check_size_for_overflow<T>(size); check_size_for_overflow<T>(size);
T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size)); T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
#ifdef EIGEN_EXCEPTIONS
try try
#endif
{ {
return construct_elements_of_array(result, size); return construct_elements_of_array(result, size);
} }
#ifdef EIGEN_EXCEPTIONS
catch (...) catch (...)
{ {
conditional_aligned_free<Align>(result); conditional_aligned_free<Align>(result);
throw; throw;
} }
#endif
} }
/** \internal Deletes objects constructed with aligned_new /** \internal Deletes objects constructed with aligned_new
@ -438,15 +450,19 @@ template<typename T, bool Align> inline T* conditional_aligned_realloc_new(T* pt
T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size)); T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
if(new_size > old_size) if(new_size > old_size)
{ {
#ifdef EIGEN_EXCEPTIONS
try try
#endif
{ {
construct_elements_of_array(result+old_size, new_size-old_size); construct_elements_of_array(result+old_size, new_size-old_size);
} }
#ifdef EIGEN_EXCEPTIONS
catch (...) catch (...)
{ {
conditional_aligned_free<Align>(result); conditional_aligned_free<Align>(result);
throw; throw;
} }
#endif
} }
return result; return result;
} }
@ -458,15 +474,19 @@ template<typename T, bool Align> inline T* conditional_aligned_new_auto(size_t s
T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size)); T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
if(NumTraits<T>::RequireInitialization) if(NumTraits<T>::RequireInitialization)
{ {
#ifdef EIGEN_EXCEPTIONS
try try
#endif
{ {
construct_elements_of_array(result, size); construct_elements_of_array(result, size);
} }
#ifdef EIGEN_EXCEPTIONS
catch (...) catch (...)
{ {
conditional_aligned_free<Align>(result); conditional_aligned_free<Align>(result);
throw; throw;
} }
#endif
} }
return result; return result;
} }
@ -480,15 +500,19 @@ template<typename T, bool Align> inline T* conditional_aligned_realloc_new_auto(
T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size)); T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
if(NumTraits<T>::RequireInitialization && (new_size > old_size)) if(NumTraits<T>::RequireInitialization && (new_size > old_size))
{ {
#ifdef EIGEN_EXCEPTIONS
try try
#endif
{ {
construct_elements_of_array(result+old_size, new_size-old_size); construct_elements_of_array(result+old_size, new_size-old_size);
} }
#ifdef EIGEN_EXCEPTIONS
catch (...) catch (...)
{ {
conditional_aligned_free<Align>(result); conditional_aligned_free<Align>(result);
throw; throw;
} }
#endif
} }
return result; return result;
} }

View File

@ -4,11 +4,30 @@
struct Foo struct Foo
{ {
static unsigned object_count;
static unsigned object_limit;
int dummy; 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 {}; class Fail : public std::exception {};
}; };
unsigned Foo::object_count = 0;
unsigned Foo::object_limit = 0;
namespace Eigen namespace Eigen
{ {
template<> template<>
@ -34,10 +53,17 @@ namespace Eigen
void test_ctorleak() void test_ctorleak()
{ {
Foo::object_count = 0;
Foo::object_limit = internal::random(0, 14 * 92 - 2);
#ifdef EIGEN_EXCEPTIONS
try try
#endif
{ {
Matrix<Foo, Dynamic, Dynamic> m(14, 92); Matrix<Foo, Dynamic, Dynamic> m(14, 92);
eigen_assert(false); // not reached eigen_assert(false); // not reached
} }
#ifdef EIGEN_EXCEPTIONS
catch (const Foo::Fail&) { /* ignore */ } catch (const Foo::Fail&) { /* ignore */ }
#endif
VERIFY_IS_EQUAL(static_cast<unsigned>(0), Foo::object_count);
} }