exceptions.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr>
  5. //
  6. // This Source Code Form is subject to the terms of the Mozilla
  7. // Public License v. 2.0. If a copy of the MPL was not distributed
  8. // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. // Various sanity tests with exceptions:
  10. // - no memory leak when a custom scalar type trow an exceptions
  11. // - todo: complete the list of tests!
  12. #define EIGEN_STACK_ALLOCATION_LIMIT 100000000
  13. #include "main.h"
  14. struct my_exception
  15. {
  16. my_exception() {}
  17. ~my_exception() {}
  18. };
  19. class ScalarWithExceptions
  20. {
  21. public:
  22. ScalarWithExceptions() { init(); }
  23. ScalarWithExceptions(const float& _v) { init(); *v = _v; }
  24. ScalarWithExceptions(const ScalarWithExceptions& other) { init(); *v = *(other.v); }
  25. ~ScalarWithExceptions() {
  26. delete v;
  27. instances--;
  28. }
  29. void init() {
  30. v = new float;
  31. instances++;
  32. }
  33. ScalarWithExceptions operator+(const ScalarWithExceptions& other) const
  34. {
  35. countdown--;
  36. if(countdown<=0)
  37. throw my_exception();
  38. return ScalarWithExceptions(*v+*other.v);
  39. }
  40. ScalarWithExceptions operator-(const ScalarWithExceptions& other) const
  41. { return ScalarWithExceptions(*v-*other.v); }
  42. ScalarWithExceptions operator*(const ScalarWithExceptions& other) const
  43. { return ScalarWithExceptions((*v)*(*other.v)); }
  44. ScalarWithExceptions& operator+=(const ScalarWithExceptions& other)
  45. { *v+=*other.v; return *this; }
  46. ScalarWithExceptions& operator-=(const ScalarWithExceptions& other)
  47. { *v-=*other.v; return *this; }
  48. ScalarWithExceptions& operator=(const ScalarWithExceptions& other)
  49. { *v = *(other.v); return *this; }
  50. bool operator==(const ScalarWithExceptions& other) const
  51. { return *v==*other.v; }
  52. bool operator!=(const ScalarWithExceptions& other) const
  53. { return *v!=*other.v; }
  54. float* v;
  55. static int instances;
  56. static int countdown;
  57. };
  58. ScalarWithExceptions real(const ScalarWithExceptions &x) { return x; }
  59. ScalarWithExceptions imag(const ScalarWithExceptions & ) { return 0; }
  60. ScalarWithExceptions conj(const ScalarWithExceptions &x) { return x; }
  61. int ScalarWithExceptions::instances = 0;
  62. int ScalarWithExceptions::countdown = 0;
  63. #define CHECK_MEMLEAK(OP) { \
  64. ScalarWithExceptions::countdown = 100; \
  65. int before = ScalarWithExceptions::instances; \
  66. bool exception_thrown = false; \
  67. try { OP; } \
  68. catch (my_exception) { \
  69. exception_thrown = true; \
  70. VERIFY(ScalarWithExceptions::instances==before && "memory leak detected in " && EIGEN_MAKESTRING(OP)); \
  71. } \
  72. VERIFY(exception_thrown && " no exception thrown in " && EIGEN_MAKESTRING(OP)); \
  73. }
  74. void memoryleak()
  75. {
  76. typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,1> VectorType;
  77. typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,Dynamic> MatrixType;
  78. {
  79. int n = 50;
  80. VectorType v0(n), v1(n);
  81. MatrixType m0(n,n), m1(n,n), m2(n,n);
  82. v0.setOnes(); v1.setOnes();
  83. m0.setOnes(); m1.setOnes(); m2.setOnes();
  84. CHECK_MEMLEAK(v0 = m0 * m1 * v1);
  85. CHECK_MEMLEAK(m2 = m0 * m1 * m2);
  86. CHECK_MEMLEAK((v0+v1).dot(v0+v1));
  87. }
  88. VERIFY(ScalarWithExceptions::instances==0 && "global memory leak detected in " && EIGEN_MAKESTRING(OP)); \
  89. }
  90. void test_exceptions()
  91. {
  92. EIGEN_TRY {
  93. CALL_SUBTEST( memoryleak() );
  94. } EIGEN_CATCH(...) {}
  95. }