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 ScalarWithExceptions real(const ScalarWithExceptions &x) { return x; }
     73 ScalarWithExceptions imag(const ScalarWithExceptions & ) { return 0; }
     74 ScalarWithExceptions conj(const ScalarWithExceptions &x) { return x; }
     75 
     76 int ScalarWithExceptions::instances = 0;
     77 int ScalarWithExceptions::countdown = 0;
     78 
     79 
     80 #define CHECK_MEMLEAK(OP) {                                 \
     81     ScalarWithExceptions::countdown = 100;                  \
     82     int before = ScalarWithExceptions::instances;           \
     83     bool exception_thrown = false;                         \
     84     try { OP; }                              \
     85     catch (my_exception) {                                  \
     86       exception_thrown = true;                              \
     87       VERIFY(ScalarWithExceptions::instances==before && "memory leak detected in " && EIGEN_MAKESTRING(OP)); \
     88     } \
     89     VERIFY(exception_thrown && " no exception thrown in " && EIGEN_MAKESTRING(OP)); \
     90   }
     91 
     92 void memoryleak()
     93 {
     94   typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,1> VectorType;
     95   typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,Dynamic> MatrixType;
     96 
     97   {
     98     int n = 50;
     99     VectorType v0(n), v1(n);
    100     MatrixType m0(n,n), m1(n,n), m2(n,n);
    101     v0.setOnes(); v1.setOnes();
    102     m0.setOnes(); m1.setOnes(); m2.setOnes();
    103     CHECK_MEMLEAK(v0 = m0 * m1 * v1);
    104     CHECK_MEMLEAK(m2 = m0 * m1 * m2);
    105     CHECK_MEMLEAK((v0+v1).dot(v0+v1));
    106   }
    107   VERIFY(ScalarWithExceptions::instances==0 && "global memory leak detected in " && EIGEN_MAKESTRING(OP)); \
    108 }
    109 
    110 void test_exceptions()
    111 {
    112   CALL_SUBTEST( memoryleak() );
    113 }
    114