CppAD: A C++ Algorithmic Differentiation Package  20130102
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-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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines