Loading [MathJax]/extensions/TeX/AMSsymbols.js
LAL 7.7.0.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
LALMallocTest.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2007 Bernd Machenschalk, Jolien Creighton
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with with program; see the file COPYING. If not, write to the
16* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17* MA 02110-1301 USA
18*/
19
20/**
21 * \file
22 * \ingroup LALMalloc_h
23 *
24 * \brief Tests the routines in \ref LALMalloc_h.
25 *
26 * ### Usage ###
27 *
28 * \code
29 * LALMallocTest
30 * \endcode
31 *
32 * ### Description ###
33 *
34 * This program has ugly code for testing the LAL memory allocation and freeing
35 * routines.
36 *
37 * ### Exit codes ###
38 *
39 * <table>
40 * <tr><th>Code</th><th>Explanation</th></tr>
41 * <tr><td> 0</td><td>Success.</td></tr>
42 * <tr><td> 1</td><td>Failure.</td></tr>
43 * </table>
44 *
45 */
46
47/** \cond DONT_DOXYGEN */
48
49#include <stdio.h>
50#include <stdlib.h>
51#include <string.h>
52#include <stdarg.h>
53#include <setjmp.h>
54#include <signal.h>
55#include <lal/LALStdio.h>
56#include <lal/LALStdlib.h>
57
58/* never use this... never! */
59void XLALClobberDebugLevel(int);
60
61char caughtMessage[1024];
62jmp_buf jump;
63FILE *mystderr;
64
65/* replacement for LALRaise */
66static int TestRaise( int sig, const char *fmt, ... )
67{
68 va_list ap;
69 va_start( ap, fmt );
70 vsnprintf( caughtMessage, sizeof( caughtMessage ), fmt, ap );
71 va_end( ap );
72 longjmp( jump, sig );
73 return -1;
74}
75
76#define STR( a ) #a
77#define XSTR( a ) STR( a )
78#define LINE ":" XSTR( __LINE__ ) ")\n"
79#define trial( func, sig, msg ) \
80do { \
81 int val; \
82 if ( ! ( val = setjmp( jump ) ) ) \
83 { \
84 func; \
85 if ( sig ) \
86 { \
87 fprintf( mystderr, "Error: no signal raised! (" #func LINE ); \
88 return 1; \
89 } \
90 } \
91 else \
92 { \
93 if ( val != sig ) \
94 { \
95 fprintf( mystderr, "Error: wrong signal raised! (" #func LINE ); \
96 fprintf( mystderr, "Received: %d %s", val, caughtMessage ); \
97 fprintf( mystderr, "Expected: %d %s\n", sig, msg ); \
98 return 1; \
99 } \
100 if ( NULL == strstr( caughtMessage, msg ) ) \
101 { \
102 fprintf( mystderr, "Error: wrong message! (" #func LINE ); \
103 fprintf( mystderr, "Received: %d %s", val, caughtMessage ); \
104 fprintf( mystderr, "Expected: %d %s\n", sig, msg ); \
105 return 1; \
106 } \
107 } \
108} \
109while ( 0 )
110#define die(msg) \
111 do { \
112 fputs("Error: " #msg "\n", mystderr); \
113 exit(1); \
114 } while (0)
115
116/* make these global so they don't get clobbered by longjmp */
117size_t i;
118size_t j;
119size_t n;
120size_t *p;
121size_t *q;
122size_t *r;
123size_t *s;
124size_t **v;
125
126static int testOK( void )
127{
128 int keep = lalDebugLevel;
129
131 trial( p = LALMalloc( 1024 * sizeof( *p ) ), 0, "" );
132 for ( i = 0; i < 1024; ++i ) p[i] = i;
133 trial( q = LALCalloc( 1024, sizeof( *q ) ), 0, "" );
134 for ( i = 0; i < 1024; ++i ) if ( q[i] ) die( memory not blanked );
135 trial( p = LALRealloc( p, 4096 * sizeof( *p ) ), 0, "" );
136 for ( i = 0; i < 1024; ++i ) if ( p[i] != i ) die( memory not copied );
137 trial( q = LALRealloc( q, 0 ), 0, "" );
138 if ( q ) die( memory not freed );
139 trial( LALCheckMemoryLeaks(), SIGSEGV, "LALCheckMemoryLeaks: memory leak\n" );
140 if ( *( p - 1 ) != (size_t)0xABadCafe ) die( wrong magic );
141 if ( *( p - 2 ) != 4096 * sizeof( *p ) ) die( wrong size );
142 trial( LALFree( p ), 0, "" );
143 trial( LALCheckMemoryLeaks(), 0, "" );
144
146 trial( p = LALMalloc( 1024 * sizeof( *p ) ), 0, "" );
147 for ( i = 0; i < 1024; ++i ) p[i] = i;
148 trial( q = LALCalloc( 1024, sizeof( *q ) ), 0, "" );
149 for ( i = 0; i < 1024; ++i ) if ( q[i] ) die( memory not blanked );
150 trial( p = LALRealloc( p, 4096 * sizeof( *p ) ), 0, "" );
151 for ( i = 0; i < 1024; ++i ) if ( p[i] != i ) die( memory not copied );
152 trial( q = LALRealloc( q, 0 ), 0, "" );
153 if ( q ) die( memory not freed );
154 trial( LALCheckMemoryLeaks(), SIGSEGV, "LALCheckMemoryLeaks: memory leak\n" );
155 trial( LALFree( p ), 0, "" );
156 trial( LALCheckMemoryLeaks(), 0, "" );
157
160 trial( p = LALMalloc( 1024 * sizeof( *p ) ), 0, "" );
161 for ( i = 0; i < 1024; ++i ) p[i] = i;
162 trial( q = LALCalloc( 1024, sizeof( *q ) ), 0, "" );
163 for ( i = 0; i < 1024; ++i ) if ( q[i] ) die( memory not blanked );
164 trial( p = LALRealloc( p, 4096 * sizeof( *p ) ), 0, "" );
165 for ( i = 0; i < 1024; ++i ) if ( p[i] != i ) die( memory not copied );
166 trial( q = LALRealloc( q, 0 ), 0, "" );
167 if ( q ) die( memory not freed );
168 trial( LALCheckMemoryLeaks(), SIGSEGV, "LALCheckMemoryLeaks: memory leak\n" );
169 if ( *( p - 1 ) != (size_t)0xABadCafe ) die( wrong magic );
170 if ( *( p - 2 ) != 4096 * sizeof( *p ) ) die( wrong size );
171 trial( LALFree( p ), 0, "" );
172 trial( LALCheckMemoryLeaks(), 0, "" );
173
175 trial( p = LALMalloc( 1024 * sizeof( *p ) ), 0, "" );
176 for ( i = 0; i < 1024; ++i ) p[i] = i;
177 trial( q = LALCalloc( 1024, sizeof( *q ) ), 0, "" );
178 for ( i = 0; i < 1024; ++i ) if ( q[i] ) die( memory not blanked );
179 trial( p = LALRealloc( p, 4096 * sizeof( *p ) ), 0, "" );
180 for ( i = 0; i < 1024; ++i ) if ( p[i] != i ) die( memory not copied );
181 trial( q = LALRealloc( q, 0 ), 0, "" );
182 /* if ( q ) die( memory not freed ); */
183 trial( LALCheckMemoryLeaks(), 0, "" );
184 trial( LALFree( p ), 0, "" );
185 trial( LALCheckMemoryLeaks(), 0, "" );
186
188 return 0;
189}
190
191
192/* test to make sure padding does what it's supposed to do */
193static int testPadding( void )
194{
195 int keep = lalDebugLevel;
196
199
200 /* try to free NULL pointer */
201 /* changed behaviour: LALFree is a no-op when passed NULL */
202 // trial( LALFree( NULL ), SIGSEGV, "error: tried to free NULL pointer" );
203
204 /* double free */
205 /* actually, this cannot be done robustly -- system can change values
206 * in unallocated space at will */
207 //trial( p = LALMalloc( 2 * sizeof( *p ) ), 0, "" );
208 //trial( LALFree( p ), 0, "" );
209 //trial( LALFree( p ), SIGSEGV, "error: tried to free a freed pointer" );
210 //trial( LALCheckMemoryLeaks(), 0, "" );
211
212 /* wrong magic */
213 trial( p = LALMalloc( 2 * sizeof( *p ) ), 0, "" );
214 p[-1] = 4;
215 trial( LALFree( p ), SIGSEGV, "error: wrong magic" );
216 p[-1] = 0xABadCafe;
217 trial( LALFree( p ), 0, "" );
218 trial( LALCheckMemoryLeaks(), 0, "" );
219
220 /* corrupt size */
221 trial( p = LALMalloc( 4 * sizeof( *p ) ), 0, "");
222 n = p[-2];
223 p[-2] = -2;
224 trial( LALFree( p ), SIGSEGV, "error: corrupt size descriptor" );
225 p[-2] = n;
226 trial( LALFree( p ), 0, "" );
227 trial( LALCheckMemoryLeaks(), 0, "" );
228
229 /* overwritten array bounds */
230 trial( p = LALMalloc( 8 * sizeof( *p ) ), 0, "" );
231 n = p[8];
232 p[8] = 0;
233 trial( LALFree( p ), SIGSEGV, "error: array bounds overwritten" );
234 p[8] = n;
235 trial( LALFree( p ), 0, "" );
236 trial( LALCheckMemoryLeaks(), 0, "" );
237
238 /* free too much memory */
239 q = malloc( 4 * sizeof( *p ) );
240 trial( p = LALMalloc( sizeof( *p ) ), 0, "" );
241 memcpy( q, p - 2, 4 * sizeof( *p ) );
242 trial( LALFree( p ), 0, "" );
243 trial( LALFree( q + 2 ), SIGSEGV, "error: lalMallocTotal too small" );
244 free( q );
245 trial( LALCheckMemoryLeaks(), 0, "" );
246
248 return 0;
249}
250
251/* test to make sure alloc list does what it's supposed to do */
252static int testAllocList( void )
253{
254 int keep = lalDebugLevel;
255
256 s = malloc( sizeof( *s ) );
257
260
261 /* empty allocation list */
262 trial( LALCheckMemoryLeaks(), 0, "" );
263 trial( LALFree( s ), SIGSEGV, "not found" );
264
265 /* can't find allocation in PopAlloc */
266 trial( p = LALMalloc( 2 * sizeof( *p ) ), 0, "" );
267 trial( q = LALMalloc( 4 * sizeof( *q ) ), 0, "" );
268 trial( r = LALMalloc( 8 * sizeof( *r ) ), 0, "" );
269 trial( LALFree( s ), SIGSEGV, "not found" );
270 trial( LALFree( p ), 0, "" );
271 trial( LALFree( r ), 0, "" );
272 trial( LALCheckMemoryLeaks(), SIGSEGV, "memory leak" );
273 trial( LALFree( q ), 0, "" );
274 trial( LALCheckMemoryLeaks(), 0, "" );
275
276 /* can't find allocation in ModAlloc */
277 /* For some reason this next test fails on Snow Leopard... */
278 /* trial( s = LALRealloc( s, 1024 ), SIGSEGV, "not found" ); */
279 trial( p = LALRealloc( NULL, 2 * sizeof( *p ) ), 0, "" );
280 /* trial( s = LALRealloc( s, 1024 ), SIGSEGV, "not found" ); */
281 trial( LALFree( p ), 0, "" );
282 trial( LALCheckMemoryLeaks(), 0, "" );
283
284 free( s );
286 return 0;
287}
288
289/* stress test the realloc routine */
290static int stressTestRealloc( void )
291{
292 const size_t nmax = 256;
293 int keep = lalDebugLevel;
294
295 v = NULL;
296
299
300 /* ascending */
301 for ( n = 1; n <= nmax; ++n )
302 {
303 size_t *u;
304 trial( v = LALRealloc( v, n * sizeof( *v ) ), 0, "" );
305 trial( u = v[n - 1] = LALRealloc( NULL, n * sizeof( **v ) ), 0, "" );
306 for ( i = 0; i < n; ++i ) u[i] = n - 1;
307 for ( i = 0; i < n; ++i )
308 {
309 trial( u = v[i] = LALRealloc( v[i], n * sizeof( *u ) ), 0, "" );
310 for ( j = 0; j < n - 1; ++j )
311 if ( u[j] != n - 1 ) die( wrong contents );
312 for ( j = 0; j < n; ++j )
313 u[j] = n;
314 }
315 }
316
317 for ( n = 0; n < nmax; ++n )
318 {
319 trial( v[n] = LALRealloc( v[n], 0 ), 0, "" );
320 }
321 trial( v = LALRealloc( v, 0 ), 0, "" );
322
323 trial( LALCheckMemoryLeaks(), 0, "" );
325 return 0;
326}
327
328
329int main( void )
330{
333
334 /* get rid of annoying messages from elsewhere */
335 setvbuf( mystderr = stdout, NULL, _IONBF, 0 );
336 FILE *fp = freopen( "/dev/null", "w", stderr );
337 if (fp == NULL) die ( unable to open /dev/null );
338
339 lalRaiseHook = TestRaise;
340
341 if ( testOK() ) return 1;
342 if ( testPadding() ) return 1;
343 if ( testAllocList() ) return 1;
344 if ( stressTestRealloc() ) return 1;
345
346 trial( LALCheckMemoryLeaks(), 0, "" );
347
348 return 0;
349}
350
351/** \endcond */
int(* lalRaiseHook)(int, const char *,...)
Definition: LALError.c:57
static const size_t magic
Definition: LALMalloc.c:260
void LALCheckMemoryLeaks(void)
Definition: LALMalloc.c:784
#define LALRealloc(p, n)
Definition: LALMalloc.h:95
#define LALCalloc(m, n)
Definition: LALMalloc.h:94
#define LALMalloc(n)
Definition: LALMalloc.h:93
#define LALFree(p)
Definition: LALMalloc.h:96
int main(int argc, char *argv[])
Definition: cache.c:25
void XLALClobberDebugLevel(int level)
Definition: LALDebugLevel.c:54
int XLALGetDebugLevel(void)
#define lalDebugLevel
Definition: LALDebugLevel.h:58
@ LALMEMDBG
enable memory debugging tools
Definition: LALDebugLevel.h:53
@ LALMEMINFOBIT
enable memory info messages
Definition: LALDebugLevel.h:40
@ LALMEMPADBIT
enable memory padding
Definition: LALDebugLevel.h:38
@ LALMEMTRKBIT
enable memory tracking
Definition: LALDebugLevel.h:39
@ LALMEMDBGBIT
enable memory debugging routines
Definition: LALDebugLevel.h:37
static const INT4 r
Definition: Random.c:82
static const INT4 q
Definition: Random.c:81
FILE * fp
Definition: tconvert.c:105