LALMallocTest.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Bernd Machenschalk, Jolien Creighton
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /*************** <lalVerbatim file="LALMallocTestCV"> *************
00021 $Id: LALMallocTest.c,v 1.3 2007/06/08 14:41:54 bema Exp $
00022 **************** </lalVerbatim> ***********************************/
00023 
00024 /* <lalLaTeX>
00025 
00026 \subsection{Program \texttt{LALMallocTest.c}}
00027 \label{s:LALMallocTest.c}
00028 
00029 Tests the routines in \verb@LALMalloc.h@.
00030 
00031 \subsubsection*{Usage}
00032 \begin{verbatim}
00033 LALMallocTest
00034 \end{verbatim}
00035 
00036 \subsubsection*{Description}
00037 
00038 This program has ugly code for testing the LAL memory allocation and freeing
00039 routines.
00040 
00041 \subsubsection*{Exit codes}
00042 \begin{tabular}{|c|l|}
00043 \hline
00044  Code & Explanation                   \\
00045 \hline
00046 \tt 0 & Success.                      \\
00047 \tt 1 & Failure.                      \\
00048 \hline
00049 \end{tabular}
00050 
00051 \subsubsection*{Uses}
00052 \begin{verbatim}
00053 lalDebugLevel
00054 LALMalloc()
00055 LALCalloc()
00056 LALRealloc()
00057 LALFree()
00058 LALCheckMemoryLeaks()
00059 \end{verbatim}
00060 
00061 \subsubsection*{Notes}
00062 
00063 \vfill{\footnotesize\input{LALMallocTestCV}}
00064 
00065 </lalLaTeX> */
00066 
00067 
00068 #include <stdio.h>
00069 #include <stdlib.h>
00070 #include <string.h>
00071 #include <stdarg.h>
00072 #include <setjmp.h>
00073 #include <signal.h>
00074 #include <lal/LALStdio.h>
00075 #include <lal/LALStdlib.h>
00076 
00077 NRCSID (LALMALLOCTESTC,"$Id: LALMallocTest.c,v 1.3 2007/06/08 14:41:54 bema Exp $");
00078 
00079 char caughtMessage[1024];
00080 jmp_buf jump;
00081 FILE *mystderr;
00082 
00083 /* replacement for LALRaise */
00084 static int TestRaise( int sig, const char *fmt, ... )
00085 {
00086   va_list ap;
00087   va_start( ap, fmt );
00088   LALVsnprintf( caughtMessage, sizeof( caughtMessage ), fmt, ap );
00089   va_end( ap );
00090   longjmp( jump, sig );
00091   return -1;
00092 }
00093 
00094 #define STR( a ) #a
00095 #define XSTR( a ) STR( a )
00096 #define LINE ":" XSTR( __LINE__ ) ")\n"
00097 #define trial( func, sig, msg ) \
00098 do { \
00099   int val; \
00100   if ( ! ( val = setjmp( jump ) ) ) \
00101   { \
00102     func; \
00103     if ( sig ) \
00104     { \
00105       fprintf( mystderr, "Error: no signal raised! (" #func LINE ); \
00106       return 1; \
00107     } \
00108   } \
00109   else \
00110   { \
00111     if ( val != sig ) \
00112     { \
00113       fprintf( mystderr, "Error: wrong signal raised! (" #func LINE ); \
00114       fprintf( mystderr, "Received: %d %s", val, caughtMessage ); \
00115       fprintf( mystderr, "Expected: %d %s\n", sig, msg ); \
00116       return 1; \
00117     } \
00118     if ( ! strstr( caughtMessage, msg ) ) \
00119     { \
00120       fprintf( mystderr, "Error: wrong message! (" #func LINE ); \
00121       fprintf( mystderr, "Received: %d %s", val, caughtMessage ); \
00122       fprintf( mystderr, "Expected: %d %s\n", sig, msg ); \
00123       return 1; \
00124     } \
00125   } \
00126 } \
00127 while ( 0 )
00128 
00129 #define die( msg ) ( fputs( "Error: " #msg "\n", mystderr ), exit( 1 ), 1 )
00130 
00131 
00132 int lalDebugLevel = LALMEMDBG;
00133 
00134 /* make these global so they don't get clobbered by longjmp */
00135 size_t   i;
00136 size_t   j;
00137 size_t   n;
00138 size_t  *p;
00139 size_t  *q;
00140 size_t  *r;
00141 size_t  *s;
00142 size_t **v;
00143 
00144 /* do a bunch of allocations/deallocations that are OK */
00145 static int testOK( void )
00146 {
00147   int keep = lalDebugLevel;
00148 
00149   lalDebugLevel &= ~( LALNMEMDBG | LALNMEMPAD | LALNMEMTRK );
00150   trial( p = LALMalloc( 1024 * sizeof( *p ) ), 0, "" );
00151   for ( i = 0; i < 1024; ++i ) p[i] = i;
00152   trial( q = LALCalloc( 1024, sizeof( *q ) ), 0, "" );
00153   for ( i = 0; i < 1024; ++i ) if ( q[i] ) die( memory not blanked ); 
00154   trial( p = LALRealloc( p, 4096 * sizeof( *p ) ), 0, "" );
00155   for ( i = 0; i < 1024; ++i ) if ( p[i] != i ) die( memory not copied );
00156   trial( q = LALRealloc( q, 0 ), 0, "" );
00157   if ( q ) die( memory not freed );
00158   trial( LALCheckMemoryLeaks(), SIGSEGV, "LALCheckMemoryLeaks: memory leak\n" );
00159   if ( *( p - 1 ) != (size_t)0xABadCafe ) die( wrong magic );
00160   if ( *( p - 2 ) != 4096 * sizeof( *p ) ) die( wrong size );
00161   trial( LALFree( p ), 0, "" );
00162   trial( LALCheckMemoryLeaks(), 0, "" );
00163 
00164   lalDebugLevel |= LALNMEMPAD;
00165   trial( p = LALMalloc( 1024 * sizeof( *p ) ), 0, "" );
00166   for ( i = 0; i < 1024; ++i ) p[i] = i;
00167   trial( q = LALCalloc( 1024, sizeof( *q ) ), 0, "" );
00168   for ( i = 0; i < 1024; ++i ) if ( q[i] ) die( memory not blanked ); 
00169   trial( p = LALRealloc( p, 4096 * sizeof( *p ) ), 0, "" );
00170   for ( i = 0; i < 1024; ++i ) if ( p[i] != i ) die( memory not copied );
00171   trial( q = LALRealloc( q, 0 ), 0, "" );
00172   if ( q ) die( memory not freed );
00173   trial( LALCheckMemoryLeaks(), SIGSEGV, "LALCheckMemoryLeaks: memory leak\n" );
00174   trial( LALFree( p ), 0, "" );
00175   trial( LALCheckMemoryLeaks(), 0, "" );
00176 
00177   lalDebugLevel &= ~LALNMEMPAD;
00178   lalDebugLevel |= LALNMEMTRK;
00179   trial( p = LALMalloc( 1024 * sizeof( *p ) ), 0, "" );
00180   for ( i = 0; i < 1024; ++i ) p[i] = i;
00181   trial( q = LALCalloc( 1024, sizeof( *q ) ), 0, "" );
00182   for ( i = 0; i < 1024; ++i ) if ( q[i] ) die( memory not blanked ); 
00183   trial( p = LALRealloc( p, 4096 * sizeof( *p ) ), 0, "" );
00184   for ( i = 0; i < 1024; ++i ) if ( p[i] != i ) die( memory not copied );
00185   trial( q = LALRealloc( q, 0 ), 0, "" );
00186   if ( q ) die( memory not freed );
00187   trial( LALCheckMemoryLeaks(), SIGSEGV, "LALCheckMemoryLeaks: memory leak\n" );
00188   if ( *( p - 1 ) != (size_t)0xABadCafe ) die( wrong magic );
00189   if ( *( p - 2 ) != 4096 * sizeof( *p ) ) die( wrong size );
00190   trial( LALFree( p ), 0, "" );
00191   trial( LALCheckMemoryLeaks(), 0, "" );
00192 
00193   lalDebugLevel |= LALNMEMDBG;
00194   trial( p = LALMalloc( 1024 * sizeof( *p ) ), 0, "" );
00195   for ( i = 0; i < 1024; ++i ) p[i] = i;
00196   trial( q = LALCalloc( 1024, sizeof( *q ) ), 0, "" );
00197   for ( i = 0; i < 1024; ++i ) if ( q[i] ) die( memory not blanked ); 
00198   trial( p = LALRealloc( p, 4096 * sizeof( *p ) ), 0, "" );
00199   for ( i = 0; i < 1024; ++i ) if ( p[i] != i ) die( memory not copied );
00200   trial( q = LALRealloc( q, 0 ), 0, "" );
00201   /* if ( q ) die( memory not freed ); */
00202   trial( LALCheckMemoryLeaks(), 0, "" );
00203   trial( LALFree( p ), 0, "" );
00204   trial( LALCheckMemoryLeaks(), 0, "" );
00205 
00206   lalDebugLevel = keep;
00207   return 0;
00208 }
00209 
00210 
00211 /* test to make sure padding does what it's supposed to do */
00212 static int testPadding( void )
00213 {
00214   int keep = lalDebugLevel;
00215 
00216   lalDebugLevel |= LALNMEMTRK;
00217   lalDebugLevel &= ~( LALNMEMDBG | LALNMEMPAD );
00218 
00219   /* try to free NULL pointer */
00220   trial( LALFree( NULL ), SIGSEGV, "error: tried to free NULL pointer" );
00221 
00222   /* wrong magic */
00223   trial( p = LALMalloc( 2 * sizeof( *p ) ), 0, "" );
00224   p[-1] = 4;
00225   trial( LALFree( p ), SIGSEGV, "error: wrong magic" );
00226   p[-1] = 0xABadCafe;
00227   trial( LALFree( p ), 0, "" );
00228   trial( LALCheckMemoryLeaks(), 0, "" );
00229 
00230   /* corrupt size */
00231   trial( p = LALMalloc( 4 * sizeof( *p ) ), 0, "");
00232   n = p[-2];
00233   p[-2] = -1;
00234   trial( LALFree( p ), SIGSEGV, "error: corrupt size descriptor" );
00235   p[-2] = n;
00236   trial( LALFree( p ), 0, "" );
00237   trial( LALCheckMemoryLeaks(), 0, "" );
00238 
00239   /* overwritten array bounds */
00240   trial( p = LALMalloc( 8 * sizeof( *p ) ), 0, "" );
00241   n = p[8];
00242   p[8] = 0;
00243   trial( LALFree( p ), SIGSEGV, "error: array bounds overwritten" );
00244   p[8] = n;
00245   trial( LALFree( p ), 0, "" );
00246   trial( LALCheckMemoryLeaks(), 0, "" );
00247 
00248   /* free too much memory */
00249   q = malloc( 4 * sizeof( *p ) );
00250   trial( p = LALMalloc( sizeof( *p ) ), 0, "" );
00251   memcpy( q, p - 2, 4 * sizeof( *p ) );
00252   trial( LALFree( p ), 0, "" );
00253   trial( LALFree( q + 2 ), SIGSEGV, "error: lalMallocTotal too small" );
00254   free( q );
00255   trial( LALCheckMemoryLeaks(), 0, "" );
00256 
00257   lalDebugLevel = keep;
00258   return 0;
00259 }
00260 
00261 /* test to make sure alloc list does what it's supposed to do */
00262 static int testAllocList( void )
00263 {
00264   int keep = lalDebugLevel;
00265 
00266   s = malloc( sizeof( *s ) );
00267 
00268   lalDebugLevel |= LALNMEMPAD;
00269   lalDebugLevel &= ~( LALNMEMDBG | LALNMEMTRK );
00270 
00271   /* empty allocation list */
00272   trial( LALCheckMemoryLeaks(), 0, "" );
00273   trial( LALFree( s ), SIGSEGV, "not found" );
00274 
00275   /* can't find allocation in PopAlloc */
00276   trial( p = LALMalloc( 2 * sizeof( *p ) ), 0, "" );
00277   trial( q = LALMalloc( 4 * sizeof( *q ) ), 0, "" );
00278   trial( r = LALMalloc( 8 * sizeof( *r ) ), 0, "" );
00279   trial( LALFree( s ), SIGSEGV, "not found" );
00280   trial( LALFree( p ), 0, "" );
00281   trial( LALFree( r ), 0, "" );
00282   trial( LALCheckMemoryLeaks(), SIGSEGV, "memory leak" );
00283   trial( LALFree( q ), 0, "" );
00284   trial( LALCheckMemoryLeaks(), 0, "" );
00285 
00286   /* can't fine allocation in ModAlloc */
00287   trial( s = LALRealloc( s, 1024 ), SIGSEGV, "not found" );
00288   trial( p = LALRealloc( NULL, 2 * sizeof( *p ) ), 0, "" );
00289   /* trial( s = LALRealloc( s, 1024 ), SIGSEGV, "not found" ); */
00290   trial( LALFree( p ), 0, "" );
00291   trial( LALCheckMemoryLeaks(), 0, "" );
00292   
00293   free( s );
00294   lalDebugLevel = keep;
00295   return 0;
00296 }
00297 
00298 /* stress test the realloc routine */
00299 static int stressTestRealloc( void )
00300 {
00301   const size_t nmax = 256;
00302   int keep = lalDebugLevel;
00303 
00304   v = NULL;
00305 
00306   lalDebugLevel &= ~( LALMEMINFO | LALNMEMDBG | LALNMEMPAD | LALNMEMTRK );
00307 
00308   /* ascending */
00309   for ( n = 1; n <= nmax; ++n )
00310   {
00311     size_t *u;
00312     trial( v = LALRealloc( v, n * sizeof( *v ) ), 0, "" );
00313     trial( u = v[n - 1] = LALRealloc( NULL, n * sizeof( **v ) ), 0, "" );
00314     for ( i = 0; i < n; ++i ) u[i] = n - 1;
00315     for ( i = 0; i < n; ++i )
00316     {
00317       trial( u = v[i] = LALRealloc( v[i], n * sizeof( *u ) ), 0, "" );
00318       for ( j = 0; j < n - 1; ++j )
00319         if ( u[j] != n - 1 ) die( wrong contents );
00320       for ( j = 0; j < n; ++j )
00321         u[j] = n;
00322     }
00323   }
00324 
00325   for ( n = 0; n < nmax; ++n )
00326   {
00327     trial( v[n] = LALRealloc( v[n], 0 ), 0, "" );
00328   }
00329   trial( v = LALRealloc( v, 0 ), 0, "" );
00330 
00331   trial( LALCheckMemoryLeaks(), 0, "" );
00332   lalDebugLevel = keep;
00333   return 0;
00334 }
00335 
00336 
00337 int main( void )
00338 {
00339 #if defined(NDEBUG) || defined(LAL_NDEBUG) /* debugging is turned off */
00340   return 77; /* don't do any testing */
00341 #else
00342   /* get rid of annoying messages from elsewhere */
00343   setvbuf( mystderr = stdout, NULL, _IONBF, 0 );
00344   freopen( "/dev/null", "w", stderr );
00345 
00346   lalRaiseHook = TestRaise;
00347 
00348   if ( lalNoDebug ) /* library was not compiled with debugging */
00349     return 77; /* don't do any testing */
00350 
00351   if ( testOK() ) return 1;
00352   if ( testPadding() ) return 1;
00353   if ( testAllocList() ) return 1;
00354   if ( stressTestRealloc() ) return 1;
00355 
00356   trial( LALCheckMemoryLeaks(), 0, "" );
00357 
00358   return 0;
00359 #endif
00360 }

Generated on Sat Aug 30 03:12:49 2008 for LAL by  doxygen 1.5.2