CppAD: A C++ Algorithmic Differentiation Package
20130918
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_MEMORY_LEAK_INCLUDED 00003 # define CPPAD_MEMORY_LEAK_INCLUDED 00004 00005 /* -------------------------------------------------------------------------- 00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 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 namespace CppAD { // BEGIN_CPPAD_NAMESPACE 00121 /*! 00122 \file memory_leak.hpp 00123 File that implements a memory check at end of a CppAD program 00124 */ 00125 00126 /*! 00127 Function that checks 00128 allocator \c thread_alloc for misuse that results in memory leaks. 00129 Deprecated routines in track_new_del.hpp and omp_alloc.hpp are also checked. 00130 00131 \param add_static [in] 00132 The amount specified by \c add_static is added to the amount 00133 of memory that is expected to be used by thread zero for static variables. 00134 00135 \return 00136 If \c add_static is non-zero, the return value is \c false. 00137 Otherwise, if one of the following errors is detected, 00138 the return value is \c true: 00139 00140 \li 00141 Thread zero does not have the expected amount of inuse memory 00142 (for static variables). 00143 \li 00144 A thread, other than thread zero, has any inuse memory. 00145 \li 00146 Any thread has available memory. 00147 00148 \par 00149 If an error is detected, diagnostic information is printed to standard 00150 output. 00151 */ 00152 inline bool memory_leak(size_t add_static = 0) 00153 { // CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL not necessary given asserts below 00154 static size_t thread_zero_static_inuse = 0; 00155 using std::cout; 00156 using std::endl; 00157 using CppAD::thread_alloc; 00158 using CppAD::omp_alloc; 00159 // -------------------------------------------------------------------- 00160 CPPAD_ASSERT_KNOWN( 00161 ! thread_alloc::in_parallel(), 00162 "memory_leak: in_parallel() is true." 00163 ); 00164 CPPAD_ASSERT_KNOWN( 00165 thread_alloc::thread_num() == 0, 00166 "memory_leak: thread_num() is not zero." 00167 ); 00168 if( add_static != 0 ) 00169 { thread_zero_static_inuse += add_static; 00170 return false; 00171 } 00172 bool leak = false; 00173 size_t thread = 0; 00174 00175 // check that memory in use for thread zero corresponds to statics 00176 size_t num_bytes = thread_alloc::inuse(thread); 00177 if( num_bytes != thread_zero_static_inuse ) 00178 { leak = true; 00179 cout << "thread zero: static inuse = " << thread_zero_static_inuse; 00180 cout << "current inuse(thread) = " << num_bytes << endl; 00181 } 00182 // check that no memory is currently available for this thread 00183 num_bytes = thread_alloc::available(thread); 00184 if( num_bytes != 0 ) 00185 { leak = true; 00186 cout << "thread zero: available = "; 00187 cout << num_bytes << endl; 00188 } 00189 for(thread = 1; thread < CPPAD_MAX_NUM_THREADS; thread++) 00190 { 00191 // check that no memory is currently in use for this thread 00192 num_bytes = thread_alloc::inuse(thread); 00193 if( num_bytes != 0 ) 00194 { leak = true; 00195 cout << "thread " << thread << ": inuse(thread) = "; 00196 cout << num_bytes << endl; 00197 } 00198 // check that no memory is currently available for this thread 00199 num_bytes = thread_alloc::available(thread); 00200 if( num_bytes != 0 ) 00201 { leak = true; 00202 cout << "thread " << thread << ": available(thread) = "; 00203 cout << num_bytes << endl; 00204 } 00205 } 00206 // ---------------------------------------------------------------------- 00207 // check track_new_del 00208 if( CPPAD_TRACK_COUNT() != 0 ) 00209 { leak = true; 00210 CppAD::TrackElement::Print(); 00211 } 00212 return leak; 00213 } 00214 00215 } // END_CPPAD_NAMESPACE 00216 # endif