CppAD: A C++ Algorithmic Differentiation Package  20130918
memory_leak.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines