Home | History | Annotate | Download | only in test
      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