You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.3 KiB

  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. int ScalarWithExceptions::instances = 0;
  59. int ScalarWithExceptions::countdown = 0;
  60. #define CHECK_MEMLEAK(OP) { \
  61. ScalarWithExceptions::countdown = 100; \
  62. int before = ScalarWithExceptions::instances; \
  63. bool exception_thrown = false; \
  64. try { OP; } \
  65. catch (my_exception) { \
  66. exception_thrown = true; \
  67. VERIFY(ScalarWithExceptions::instances==before && "memory leak detected in " && EIGEN_MAKESTRING(OP)); \
  68. } \
  69. VERIFY(exception_thrown && " no exception thrown in " && EIGEN_MAKESTRING(OP)); \
  70. }
  71. void memoryleak()
  72. {
  73. typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,1> VectorType;
  74. typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,Dynamic> MatrixType;
  75. {
  76. int n = 50;
  77. VectorType v0(n), v1(n);
  78. MatrixType m0(n,n), m1(n,n), m2(n,n);
  79. v0.setOnes(); v1.setOnes();
  80. m0.setOnes(); m1.setOnes(); m2.setOnes();
  81. CHECK_MEMLEAK(v0 = m0 * m1 * v1);
  82. CHECK_MEMLEAK(m2 = m0 * m1 * m2);
  83. CHECK_MEMLEAK((v0+v1).dot(v0+v1));
  84. }
  85. VERIFY(ScalarWithExceptions::instances==0 && "global memory leak detected in " && EIGEN_MAKESTRING(OP)); \
  86. }
  87. void test_exceptions()
  88. {
  89. CALL_SUBTEST( memoryleak() );
  90. }