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 (at) 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 10 11 // Various sanity tests with exceptions: 12 // - no memory leak when a custom scalar type trow an exceptions 13 // - todo: complete the list of tests! 14 15 #define EIGEN_STACK_ALLOCATION_LIMIT 100000000 16 17 #include "main.h" 18 19 struct my_exception 20 { 21 my_exception() {} 22 ~my_exception() {} 23 }; 24 25 class ScalarWithExceptions 26 { 27 public: 28 ScalarWithExceptions() { init(); } 29 ScalarWithExceptions(const float& _v) { init(); *v = _v; } 30 ScalarWithExceptions(const ScalarWithExceptions& other) { init(); *v = *(other.v); } 31 ~ScalarWithExceptions() { 32 delete v; 33 instances--; 34 } 35 36 void init() { 37 v = new float; 38 instances++; 39 } 40 41 ScalarWithExceptions operator+(const ScalarWithExceptions& other) const 42 { 43 countdown--; 44 if(countdown<=0) 45 throw my_exception(); 46 return ScalarWithExceptions(*v+*other.v); 47 } 48 49 ScalarWithExceptions operator-(const ScalarWithExceptions& other) const 50 { return ScalarWithExceptions(*v-*other.v); } 51 52 ScalarWithExceptions operator*(const ScalarWithExceptions& other) const 53 { return ScalarWithExceptions((*v)*(*other.v)); } 54 55 ScalarWithExceptions& operator+=(const ScalarWithExceptions& other) 56 { *v+=*other.v; return *this; } 57 ScalarWithExceptions& operator-=(const ScalarWithExceptions& other) 58 { *v-=*other.v; return *this; } 59 ScalarWithExceptions& operator=(const ScalarWithExceptions& other) 60 { *v = *(other.v); return *this; } 61 62 bool operator==(const ScalarWithExceptions& other) const 63 { return *v==*other.v; } 64 bool operator!=(const ScalarWithExceptions& other) const 65 { return *v!=*other.v; } 66 67 float* v; 68 static int instances; 69 static int countdown; 70 }; 71 72 int ScalarWithExceptions::instances = 0; 73 int ScalarWithExceptions::countdown = 0; 74 75 76 #define CHECK_MEMLEAK(OP) { \ 77 ScalarWithExceptions::countdown = 100; \ 78 int before = ScalarWithExceptions::instances; \ 79 bool exception_thrown = false; \ 80 try { OP; } \ 81 catch (my_exception) { \ 82 exception_thrown = true; \ 83 VERIFY(ScalarWithExceptions::instances==before && "memory leak detected in " && EIGEN_MAKESTRING(OP)); \ 84 } \ 85 VERIFY(exception_thrown && " no exception thrown in " && EIGEN_MAKESTRING(OP)); \ 86 } 87 88 void memoryleak() 89 { 90 typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,1> VectorType; 91 typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,Dynamic> MatrixType; 92 93 { 94 int n = 50; 95 VectorType v0(n), v1(n); 96 MatrixType m0(n,n), m1(n,n), m2(n,n); 97 v0.setOnes(); v1.setOnes(); 98 m0.setOnes(); m1.setOnes(); m2.setOnes(); 99 CHECK_MEMLEAK(v0 = m0 * m1 * v1); 100 CHECK_MEMLEAK(m2 = m0 * m1 * m2); 101 CHECK_MEMLEAK((v0+v1).dot(v0+v1)); 102 } 103 VERIFY(ScalarWithExceptions::instances==0 && "global memory leak detected in " && EIGEN_MAKESTRING(OP)); \ 104 } 105 106 void test_exceptions() 107 { 108 CALL_SUBTEST( memoryleak() ); 109 } 110