diff options
author | 2014-07-06 06:58:13 +0200 | |
---|---|---|
committer | 2014-07-06 06:58:13 +0200 | |
commit | 58687aa5e638d365d5e41c1e6c66cbfc44fce85f (patch) | |
tree | af5ea0fa2a0de994a4d3522e94ff83852e30adb0 /test | |
parent | 339f14b8d1b73db0366afc3a497d566cecf72e1b (diff) |
Avoid memory leak when constructor of user-defined type throws exception.
The added check `ctorleak.cpp` demonstrates how the leak can be reproduced.
The test appears to pass but it is leaking the storage of the (not created)
matrix. I don't know how to make this test fail in the existing test suite but
you can run it through Valgrind (or another debugger) to verify the leak.
$ ./check.sh ctorleak && valgrind --leak-check=full ./test/ctorleak
This patch fixes this leak by adding some try-catch-delete-rethrow blocks to
`Eigen/src/Core/util/Memory.h`.
Diffstat (limited to 'test')
-rw-r--r-- | test/CMakeLists.txt | 2 | ||||
-rw-r--r-- | test/ctorleak.cpp | 43 |
2 files changed, 45 insertions, 0 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4521d07e4..fed5c0e06 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -251,6 +251,8 @@ ei_add_test(bicgstab) ei_add_test(sparselu) ei_add_test(sparseqr) +ei_add_test(ctorleak) + # ei_add_test(denseLM) if(QT4_FOUND) diff --git a/test/ctorleak.cpp b/test/ctorleak.cpp new file mode 100644 index 000000000..72ab94b66 --- /dev/null +++ b/test/ctorleak.cpp @@ -0,0 +1,43 @@ +#include "main.h" + +#include <exception> // std::exception + +struct Foo +{ + int dummy; + Foo() { if (!internal::random(0, 10)) throw Foo::Fail(); } + class Fail : public std::exception {}; +}; + +namespace Eigen +{ + template<> + struct NumTraits<Foo> + { + typedef double Real; + typedef double NonInteger; + typedef double Nested; + enum + { + IsComplex = 0, + IsInteger = 1, + ReadCost = -1, + AddCost = -1, + MulCost = -1, + IsSigned = 1, + RequireInitialization = 1 + }; + static inline Real epsilon() { return 1.0; } + static inline Real dummy_epsilon() { return 0.0; } + }; +} + +void test_ctorleak() +{ + try + { + Matrix<Foo, Dynamic, Dynamic> m(14, 92); + eigen_assert(false); // not reached + } + catch (const Foo::Fail&) { /* ignore */ } +} |