CppAD: A C++ Algorithmic Differentiation Package
20130102
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_MEMORY_LEAK_INCLUDED 00003 # define CPPAD_MEMORY_LEAK_INCLUDED 00004 00005 /* -------------------------------------------------------------------------- 00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell 00007 00008 CppAD is distributed under multiple licenses. This distribution is under 00009 the terms of the 00010 Eclipse Public License Version 1.0. 00011 00012 A copy of this license is included in the COPYING file of this distribution. 00013 Please visit http://www.coin-or.org/CppAD/ for information on other licenses. 00014 -------------------------------------------------------------------------- */ 00015 /* 00016 $begin memory_leak$$ 00017 $spell 00018 num 00019 alloc 00020 hpp 00021 bool 00022 inuse 00023 $$ 00024 00025 $section Memory Leak Detection$$ 00026 $index memory_leak$$ 00027 $index leak, memory$$ 00028 $index check, memory leak$$ 00029 $index static, memory leak check$$ 00030 00031 $head Deprecated$$ 00032 $index deprecated, memory leak$$ 00033 This routine has been deprecated. 00034 You should instead use the routine $cref ta_free_all$$. 00035 00036 $head Syntax$$ 00037 $icode%flag% = %memory_leak() 00038 %$$ 00039 $icode%flag% = %memory_leak(%add_static%)%$$ 00040 00041 $head Purpose$$ 00042 This routine checks that the are no memory leaks 00043 caused by improper use of $cref thread_alloc$$ memory allocator. 00044 The deprecated memory allocator $cref TrackNewDel$$ is also checked. 00045 Memory errors in the deprecated $cref omp_alloc$$ allocator are 00046 reported as being in $code thread_alloc$$. 00047 00048 $head thread$$ 00049 It is assumed that $cref/in_parallel()/ta_in_parallel/$$ is false 00050 and $cref/thread_num/ta_thread_num/$$ is zero when 00051 $code memory_leak$$ is called. 00052 00053 $head add_static$$ 00054 This argument has prototype 00055 $codei% 00056 size_t %add_static% 00057 %$$ 00058 and its default value is zero. 00059 Static variables hold onto memory forever. 00060 If the argument $icode add_static$$ is present (and non-zero), 00061 $code memory_leak$$ adds this amount of memory to the 00062 $cref/inuse/ta_inuse/$$ sum that corresponds to 00063 static variables in the program. 00064 A call with $icode add_static$$ should be make after 00065 a routine that has static variables which 00066 use $cref/get_memory/ta_get_memory/$$ to allocate memory. 00067 The value of $icode add_static$$ should be the difference of 00068 $codei% 00069 thread_alloc::inuse(0) 00070 %$$ 00071 before and after the call. 00072 Since multiple statics may be allocated in different places in the program, 00073 it is expected that there will be multiple calls 00074 that use this option. 00075 00076 $head flag$$ 00077 The return value $icode flag$$ has prototype 00078 $codei% 00079 bool %flag% 00080 %$$ 00081 If $icode add_static$$ is non-zero, 00082 the return value for $code memory_leak$$ is false. 00083 Otherwise, the return value for $code memory_leak$$ should be false 00084 (indicating that the only allocated memory corresponds to static variables). 00085 00086 $head inuse$$ 00087 It is assumed that, when $code memory_leak$$ is called, 00088 there should not be any memory 00089 $cref/inuse/ta_inuse/$$ or $cref omp_inuse$$ for any thread 00090 (except for inuse memory corresponding to static variables). 00091 If there is, a message is printed and $code memory_leak$$ returns false. 00092 00093 $head available$$ 00094 It is assumed that, when $code memory_leak$$ is called, 00095 there should not be any memory 00096 $cref/available/ta_available/$$ or $cref omp_available$$ for any thread; 00097 i.e., it all has been returned to the system. 00098 If there is memory still available for any thread, 00099 $code memory_leak$$ returns false. 00100 00101 $head TRACK_COUNT$$ 00102 It is assumed that, when $code memory_leak$$ is called, 00103 $cref/TrackCount/TrackNewDel/TrackCount/$$ will return a zero value. 00104 If it returns a non-zero value, 00105 $code memory_leak$$ returns false. 00106 00107 $head Error Message$$ 00108 If this is the first call to $code memory_leak$$, no message is printed. 00109 Otherwise, if it returns true, an error message is printed 00110 to standard output describing the memory leak that was detected. 00111 00112 $end 00113 */ 00114 # include <iostream> 00115 # include <cppad/local/define.hpp> 00116 # include <cppad/omp_alloc.hpp> 00117 # include <cppad/thread_alloc.hpp> 00118 # include <cppad/track_new_del.hpp> 00119 00120 CPPAD_BEGIN_NAMESPACE 00121 /*! 00122 \defgroup memory_leak_hpp memory_leak.hpp 00123 \{ 00124 \file memory_leak.hpp 00125 File that implements a memory check at end of a CppAD program 00126 */ 00127 00128 /*! 00129 Function that checks 00130 allocator \c thread_alloc for misuse that results in memory leaks. 00131 Deprecated routines in track_new_del.hpp and omp_alloc.hpp are also checked. 00132 00133 \param add_static [in] 00134 The amount specified by \c add_static is added to the amount 00135 of memory that is expected to be used by thread zero for static variables. 00136 00137 \return 00138 If \c add_static is non-zero, the return value is \c false. 00139 Otherwise, if one of the following errors is detected, 00140 the return value is \c true: 00141 00142 \li 00143 Thread zero does not have the expected amount of inuse memory 00144 (for static variables). 00145 \li 00146 A thread, other than thread zero, has any inuse memory. 00147 \li 00148 Any thread has available memory. 00149 00150 \par 00151 If an error is detected, diagnostic information is printed to standard 00152 output. 00153 */ 00154 inline bool memory_leak(size_t add_static = 0) 00155 { // CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL not necessary given asserts below 00156 static size_t thread_zero_static_inuse = 0; 00157 using std::cout; 00158 using std::endl; 00159 using CppAD::thread_alloc; 00160 using CppAD::omp_alloc; 00161 // -------------------------------------------------------------------- 00162 CPPAD_ASSERT_KNOWN( 00163 ! thread_alloc::in_parallel(), 00164 "memory_leak: in_parallel() is true." 00165 ); 00166 CPPAD_ASSERT_KNOWN( 00167 thread_alloc::thread_num() == 0, 00168 "memory_leak: thread_num() is not zero." 00169 ); 00170 if( add_static != 0 ) 00171 { thread_zero_static_inuse += add_static; 00172 return false; 00173 } 00174 bool leak = false; 00175 size_t thread = 0; 00176 00177 // check that memory in use for thread zero corresponds to statics 00178 size_t num_bytes = thread_alloc::inuse(thread); 00179 if( num_bytes != thread_zero_static_inuse ) 00180 { leak = true; 00181 cout << "thread zero: static inuse = " << thread_zero_static_inuse; 00182 cout << "current inuse(thread) = " << num_bytes << endl; 00183 } 00184 // check that no memory is currently available for this thread 00185 num_bytes = thread_alloc::available(thread); 00186 if( num_bytes != 0 ) 00187 { leak = true; 00188 cout << "thread zero: available = "; 00189 cout << num_bytes << endl; 00190 } 00191 for(thread = 1; thread < CPPAD_MAX_NUM_THREADS; thread++) 00192 { 00193 // check that no memory is currently in use for this thread 00194 num_bytes = thread_alloc::inuse(thread); 00195 if( num_bytes != 0 ) 00196 { leak = true; 00197 cout << "thread " << thread << ": inuse(thread) = "; 00198 cout << num_bytes << endl; 00199 } 00200 // check that no memory is currently available for this thread 00201 num_bytes = thread_alloc::available(thread); 00202 if( num_bytes != 0 ) 00203 { leak = true; 00204 cout << "thread " << thread << ": available(thread) = "; 00205 cout << num_bytes << endl; 00206 } 00207 } 00208 // ---------------------------------------------------------------------- 00209 // check track_new_del 00210 if( CPPAD_TRACK_COUNT() != 0 ) 00211 { leak = true; 00212 CppAD::TrackElement::Print(); 00213 } 00214 return leak; 00215 } 00216 00217 /*! \} */ 00218 CPPAD_END_NAMESPACE 00219 # endif