blob: c28cd1b0b22478b9eed31fc0b35458ec049a67fe [file] [log] [blame]
Gael Guennebaud5541bcb2011-05-23 14:20:49 +02001// 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// Eigen is free software; you can redistribute it and/or
7// modify it under the terms of the GNU Lesser General Public
8// License as published by the Free Software Foundation; either
9// version 3 of the License, or (at your option) any later version.
10//
11// Alternatively, you can redistribute it and/or
12// modify it under the terms of the GNU General Public License as
13// published by the Free Software Foundation; either version 2 of
14// the License, or (at your option) any later version.
15//
16// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
17// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public
22// License and a copy of the GNU General Public License along with
23// Eigen. If not, see <http://www.gnu.org/licenses/>.
24
25
26// Various sanity tests with exceptions:
27// - no memory leak when a custom scalar type trow an exceptions
28// - todo: complete the list of tests!
29
30#define EIGEN_STACK_ALLOCATION_LIMIT 100000000
31
32#include "main.h"
33
34struct my_exception
35{
36 my_exception() {}
37 ~my_exception() {}
38};
39
40class ScalarWithExceptions
41{
42 public:
43 ScalarWithExceptions() { init(); }
44 ScalarWithExceptions(const float& _v) { init(); *v = _v; }
45 ScalarWithExceptions(const ScalarWithExceptions& other) { init(); *v = *(other.v); }
46 ~ScalarWithExceptions() {
47 delete v;
48 instances--;
49 }
50
51 void init() {
52 v = new float;
53 instances++;
54 }
55
56 ScalarWithExceptions operator+(const ScalarWithExceptions& other) const
57 {
58 countdown--;
59 if(countdown<=0)
60 throw my_exception();
61 return ScalarWithExceptions(*v+*other.v);
62 }
63
64 ScalarWithExceptions operator-(const ScalarWithExceptions& other) const
65 { return ScalarWithExceptions(*v-*other.v); }
66
67 ScalarWithExceptions operator*(const ScalarWithExceptions& other) const
68 { return ScalarWithExceptions((*v)*(*other.v)); }
69
70 ScalarWithExceptions& operator+=(const ScalarWithExceptions& other)
71 { *v+=*other.v; return *this; }
72 ScalarWithExceptions& operator-=(const ScalarWithExceptions& other)
73 { *v-=*other.v; return *this; }
74 ScalarWithExceptions& operator=(const ScalarWithExceptions& other)
75 { *v = *(other.v); return *this; }
76
77 bool operator==(const ScalarWithExceptions& other) const
78 { return *v==*other.v; }
79 bool operator!=(const ScalarWithExceptions& other) const
80 { return *v!=*other.v; }
81
82 float* v;
83 static int instances;
84 static int countdown;
85};
86
87int ScalarWithExceptions::instances = 0;
88int ScalarWithExceptions::countdown = 0;
89
90
91#define CHECK_MEMLEAK(OP) { \
92 ScalarWithExceptions::countdown = 100; \
93 int before = ScalarWithExceptions::instances; \
94 bool exception_thrown = false; \
95 try { OP; } \
96 catch (my_exception) { \
97 exception_thrown = true; \
98 VERIFY(ScalarWithExceptions::instances==before && "memory leak detected in " && EIGEN_MAKESTRING(OP)); \
99 } \
100 VERIFY(exception_thrown && " no exception thrown in " && EIGEN_MAKESTRING(OP)); \
101 }
102
103void memoryleak()
104{
105 typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,1> VectorType;
106 typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,Dynamic> MatrixType;
107
108 {
109 int n = 50;
110 VectorType v0(n), v1(n);
111 MatrixType m0(n,n), m1(n,n), m2(n,n);
112 v0.setOnes(); v1.setOnes();
113 m0.setOnes(); m1.setOnes(); m2.setOnes();
114 CHECK_MEMLEAK(v0 = m0 * m1 * v1);
115 CHECK_MEMLEAK(m2 = m0 * m1 * m2);
116 CHECK_MEMLEAK((v0+v1).dot(v0+v1));
117 }
118 VERIFY(ScalarWithExceptions::instances==0 && "global memory leak detected in " && EIGEN_MAKESTRING(OP)); \
119}
120
121void test_exceptions()
122{
123 CALL_SUBTEST( memoryleak() );
124}