LAL 7.7.0.1-678514e
LALMalloc.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2016 Karl Wette
3* Copyright (C) 2007 Jolien Creighton, Josh Willis
4*
5* This program is free software; you can redistribute it and/or modify
6* it under the terms of the GNU General Public License as published by
7* the Free Software Foundation; either version 2 of the License, or
8* (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with with program; see the file COPYING. If not, write to the
17* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18* MA 02110-1301 USA
19*/
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <signal.h>
25
26#include <config.h>
27#include <lal/LALMalloc.h>
28#include <lal/LALStdio.h>
29#include <lal/LALError.h>
30
31#ifdef __GNUC__
32#define UNUSED __attribute__ ((unused))
33#else
34#define UNUSED
35#endif
36
37/* global variables */
38size_t lalMallocTotal = 0; /**< current amount of memory allocated by process */
39size_t lalMallocTotalPeak = 0; /**< peak amount of memory allocated so far */
40
41/*
42 *
43 * XLAL Routines.
44 *
45 */
46
47#define XLAL_TEST_POINTER( ptr, size ) \
48 if ( ! (ptr) && (size) ) \
49 XLAL_ERROR_NULL( XLAL_ENOMEM ); \
50 else (void)(0)
51#define XLAL_TEST_POINTER_LONG( ptr, size, file, line ) \
52 if ( ! (ptr) && (size) ) \
53 { \
54 XLALPrintError( "XLALError - %s in %s:%d", __func__, file, line ); \
55 XLAL_ERROR_NULL( XLAL_ENOMEM ); \
56 } \
57 else (void)(0)
58#define XLAL_TEST_POINTER_ALIGNED( ptr, size, retval ) \
59 if ( ! (ptr) && (size) && (retval) ) \
60 XLAL_ERROR_NULL( XLAL_ENOMEM ); \
61 else (void)(0)
62#define XLAL_TEST_POINTER_ALIGNED_LONG( ptr, size, retval, file, line ) \
63 if ( ! (ptr) && (size) && (retval) ) \
64 { \
65 XLALPrintError( "XLALError - %s in %s:%d", __func__, file, line ); \
66 XLAL_ERROR_NULL( XLAL_ENOMEM ); \
67 } \
68 else (void)(0)
69
70void *(XLALMalloc) (size_t n) {
71 void *p;
72 p = LALMallocShort(n);
74 return p;
75}
76
77void *XLALMallocLong(size_t n, const char *file, int line)
78{
79 void *p;
80 p = LALMallocLong(n, file, line);
81 XLAL_TEST_POINTER_LONG(p, n, file, line);
82 return p;
83}
84
85void *(XLALCalloc) (size_t m, size_t n) {
86 void *p;
87 p = LALCallocShort(m, n);
88 XLAL_TEST_POINTER(p, m && n);
89 return p;
90}
91
92void *XLALCallocLong(size_t m, size_t n, const char *file, int line)
93{
94 void *p;
95 p = LALCallocLong(m, n, file, line);
96 XLAL_TEST_POINTER_LONG(p, m && n, file, line);
97 return p;
98}
99
100void *(XLALRealloc) (void *p, size_t n) {
101 p = LALReallocShort(p, n);
103 return p;
104}
105
106void *XLALReallocLong(void *p, size_t n, const char *file, int line)
107{
108 p = LALReallocLong(p, n, file, line);
109 XLAL_TEST_POINTER_LONG(p, n, file, line);
110 return p;
111}
112
113void (XLALFree) (void *p)
114{
115 if (p)
117 return;
118}
119
120void XLALFreeLong(void *p, const char *file UNUSED, int line UNUSED)
121{
122 if (p)
123 LALFreeLong(p, file, line);
124 return;
125}
126
127/*
128 * Aligned memory routines.
129 */
130
131#if LAL_FFTW3_MEMALIGN_ENABLED
132
133#ifndef HAVE_POSIX_MEMALIGN
134#error no posix_memalign available
135#endif
136
137int XLALIsMemoryAligned(void *ptr)
138{
139 return LAL_IS_MEMORY_ALIGNED(ptr);
140}
141
142void *XLALMallocAlignedLong(size_t size, const char *file, int line)
143{
144 void *p=NULL;
145 int retval;
146 retval = posix_memalign(&p, LAL_MEM_ALIGNMENT, size);
147 XLAL_TEST_POINTER_ALIGNED_LONG(p, size, retval, file, line);
148 return p;
149}
150
151void *(XLALMallocAligned)(size_t size)
152{
153 void *p=NULL;
154 int retval;
155 retval = posix_memalign(&p, LAL_MEM_ALIGNMENT, size);
156 XLAL_TEST_POINTER_ALIGNED(p, size, retval);
157 return p;
158}
159
160void *XLALCallocAlignedLong(size_t nelem, size_t elsize, const char *file, int line)
161{
162 size_t size = nelem * elsize;
163 void *p = XLALMallocAlignedLong(size, file, line);
164 XLAL_TEST_POINTER_LONG(p, size, file, line);
165 memset(p, 0, size);
166 return p;
167}
168
169void *(XLALCallocAligned)(size_t nelem, size_t elsize)
170{
171 size_t size = nelem * elsize;
172 void *p = (XLALMallocAligned)(size);
173 XLAL_TEST_POINTER(p, size);
174 memset(p, 0, size);
175 return p;
176}
177
178void *XLALReallocAlignedLong(void *ptr, size_t size, const char *file, int line)
179{
180 void *p;
181 if (ptr == NULL)
182 return XLALMallocAlignedLong(size, file, line);
183 if (size == 0) {
184 XLALFreeAligned(ptr);
185 return NULL;
186 }
187 p = realloc(ptr, size); /* use ordinary realloc */
188 if (XLALIsMemoryAligned(p))
189 return p;
190 /* need to do a new allocation and a memcpy, inefficient... */
191 ptr = XLALMallocAlignedLong(size, file, line);
192 memcpy(ptr, p, size);
193 free(p);
194 return ptr;
195}
196
197void *(XLALReallocAligned)(void *ptr, size_t size)
198{
199 void *p;
200 if (ptr == NULL)
201 return XLALMallocAligned(size);
202 if (size == 0) {
203 XLALFreeAligned(ptr);
204 return NULL;
205 }
206 p = realloc(ptr, size); /* use ordinary realloc */
207 if (XLALIsMemoryAligned(p))
208 return p;
209 /* need to do a new allocation and a memcpy, inefficient... */
210 ptr = XLALMallocAligned(size);
211 memcpy(ptr, p, size);
212 free(p);
213 return ptr;
214}
215
216void XLALFreeAligned(void *ptr)
217{
218 free(ptr); /* use ordinary free */
219}
220
221#endif /* LAL_FFTW3_MEMALIGN_ENABLED */
222
223/*
224 *
225 * LAL Routines... only if compiled with debugging enabled.
226 * (otherwise the LALMalloc-family reverts to the standard malloc-family).
227 *
228 */
229
230
231#ifndef LAL_MEMORY_FUNCTIONS_DISABLED
232
233#ifdef LAL_PTHREAD_LOCK
234#include <pthread.h>
235static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
236#else
237#define pthread_mutex_lock( pmut )
238#define pthread_mutex_unlock( pmut )
239#endif
240
241#include <lal/LALStdlib.h>
242
243/* global variables to assist in memory debugging */
244/* watch the value of these variables to find a particular alloc/free */
245char *lalMemDbgArgPtr = NULL; /* set to ptr arg in free or realloc */
246char *lalMemDbgRetPtr = NULL; /* set to ptr returned in alloc functions */
247char *lalMemDbgPtr = NULL; /* set in both cases */
248char *lalMemDbgUsrPtr = NULL; /* avaliable global memory pointer for user */
249void **lalMemDbgUsrHndl = NULL; /* avaliable global memory handle for user */
250int lalIsMemDbgArgPtr; /* ( lalMemDbgUsrPtr == lalMemDbgArgPtr ) */
251int lalIsMemDbgRetPtr; /* ( lalMemDbgUsrPtr == lalMemDbgRetPtr ) */
252int lalIsMemDbgPtr; /* ( lalMemDbgUsrPtr == lalMemDbgPtr ) */
253
254
255enum { nprefix = 2 };
256static const size_t prefix = nprefix * sizeof(size_t);
257static const size_t padFactor = 2;
258static const size_t padding = 0xDeadBeef;
259static const size_t repadding = 0xBeefDead;
260static const size_t magic = 0xABadCafe;
261
262#define allocsz(n) ((lalDebugLevel & LALMEMPADBIT) ? (padFactor * (n) + prefix) : (n))
263
264/* Hash table implementation taken from src/utilities/LALHashTbl.c */
265
266static struct allocNode {
267 void *addr;
268 size_t size;
269 const char *file;
270 int line;
271} **alloc_data = NULL; /* Allocation hash table with open addressing and linear probing */
272static int alloc_data_len = 0; /* Size of the memory block 'alloc_data', in number of elements */
273static int alloc_n = 0; /* Number of valid elements in the hash */
274static int alloc_q = 0; /* Number of non-NULL elements in the hash */
275
276/* Special allocation hash table element value to indicate elements that have been deleted */
277static const void *hash_del = 0;
278#define DEL ((struct allocNode*) &hash_del)
279
280/* Evaluates to the hash value of x, restricted to the length of the allocation hash table */
281#define HASHIDX(x) ((int)( ((intptr_t)( (x)->addr )) % alloc_data_len ))
282
283/* Increment the next hash index, restricted to the length of the allocation hash table */
284#define INCRIDX(i) do { if (++(i) == alloc_data_len) { (i) = 0; } } while(0)
285
286/* Evaluates true if the elements x and y are equal */
287#define EQUAL(x, y) ((x)->addr == (y)->addr)
288
289/* need this to turn off gcc warnings about unused functions */
290#ifdef __GNUC__
291#define UNUSED __attribute__ ((unused))
292#else
293#define UNUSED
294#endif
295
296/* Resize and rebuild the allocation allocation hash table */
297UNUSED static int AllocHashTblResize(void)
298{
299 struct allocNode **old_data = alloc_data;
300 int old_data_len = alloc_data_len;
301 alloc_data_len = 2;
302 while (alloc_data_len < 3*alloc_n) {
303 alloc_data_len *= 2;
304 }
305 alloc_data = calloc(alloc_data_len, sizeof(alloc_data[0]));
306 if (alloc_data == NULL) {
307 return 0;
308 }
310 for (int k = 0; k < old_data_len; ++k) {
311 if (old_data[k] != NULL && old_data[k] != DEL) {
312 int i = HASHIDX(old_data[k]);
313 while (alloc_data[i] != NULL) {
314 INCRIDX(i);
315 }
316 alloc_data[i] = old_data[k];
317 }
318 }
319 free(old_data);
320 return 1;
321}
322
323/* Find node in allocation hash table */
324UNUSED static struct allocNode *AllocHashTblFind(struct allocNode *x)
325{
326 struct allocNode *y = NULL;
327 if (alloc_data_len > 0) {
328 int i = HASHIDX(x);
329 while (alloc_data[i] != NULL) {
330 y = alloc_data[i];
331 if (y != DEL && EQUAL(x, y)) {
332 return y;
333 }
334 INCRIDX(i);
335 }
336 }
337 return NULL;
338}
339
340/* Add node to allocation hash table */
341UNUSED static int AllocHashTblAdd(struct allocNode *x)
342{
343 if (2*(alloc_q + 1) > alloc_data_len) {
344 /* Resize allocation hash table to preserve maximum 50% occupancy */
345 if (!AllocHashTblResize()) {
346 return 0;
347 }
348 }
349 int i = HASHIDX(x);
350 while (alloc_data[i] != NULL && alloc_data[i] != DEL) {
351 INCRIDX(i);
352 }
353 if (alloc_data[i] == NULL) {
354 ++alloc_q;
355 }
356 ++alloc_n;
357 alloc_data[i] = x;
358 return 1;
359}
360
361/* Extract node from allocation hash table */
362UNUSED static struct allocNode *AllocHashTblExtract(struct allocNode *x)
363{
364 if (alloc_data_len > 0) {
365 int i = HASHIDX(x);
366 while (alloc_data[i] != NULL) {
367 struct allocNode *y = alloc_data[i];
368 if (y != DEL && EQUAL(x, y)) {
369 alloc_data[i] = DEL;
370 --alloc_n;
371 if (alloc_n == 0) {
372 /* Free all hash table memory */
373 free(alloc_data);
374 alloc_data = NULL;
375 alloc_data_len = 0;
376 alloc_q = 0;
377 } else if (8*alloc_n < alloc_data_len) {
378 /* Resize hash table to preserve minimum 50% occupancy */
379 if (!AllocHashTblResize()) {
380 return NULL;
381 }
382 }
383 return y;
384 }
385 INCRIDX(i);
386 }
387 }
388 return NULL;
389}
390
391
392/* Useful function for debugging */
393/* Checks to make sure alloc list is OK */
394/* Returns 0 if list is corrupted; 1 if list is OK */
395UNUSED static int CheckAllocList(void)
396{
397 int count = 0;
398 size_t total = 0;
399 for (int k = 0; k < alloc_data_len; ++k) {
400 if (alloc_data[k] != NULL && alloc_data[k] != DEL) {
401 ++count;
402 total += alloc_data[k]->size;
403 }
404 }
405 return count == alloc_n && total == lalMallocTotal;
406}
407
408/* Useful function for debugging */
409/* Finds the node of the alloc list for the desired alloc */
410/* Returns NULL if not found */
411UNUSED static struct allocNode *FindAlloc(void *p)
412{
413 struct allocNode key = { .addr = p };
414 return AllocHashTblFind(&key);
415}
416
417
418static void *PadAlloc(size_t * p, size_t n, int keep, const char *func, const char *file, int line)
419{
420 size_t i;
421
422 if (!(lalDebugLevel & LALMEMPADBIT)) {
423 return p;
424 }
425
426 if (!p) {
427 return NULL;
428 }
429
431 XLALPrintError("%s meminfo: allocating %zu bytes at address %p in %s:%d\n",
432 func, n, p + nprefix, file, line);
433 }
434
435 /* store the size in a known position */
436 p[0] = n;
437 p[1] = magic;
438
439 /* pad the memory */
440 for (i = keep ? n : 0; i < padFactor * n; ++i) {
441 ((char *) p)[i + prefix] = (char) (i ^ padding);
442 }
443
444 pthread_mutex_lock(&mut);
445 lalMallocTotal += n;
448
449 return (void *) (((char *) p) + prefix);
450}
451
452
453static void *UnPadAlloc(void *p, int keep, const char *func, const char *file, int line)
454{
455 size_t n;
456 size_t i;
457 size_t *q;
458 char *s;
459
460 if (!(lalDebugLevel & LALMEMPADBIT)) {
461 return p;
462 }
463
464 if (!p || !(q = ((size_t *) p) - nprefix)) {
465 lalRaiseHook(SIGSEGV, "%s error: tried to free NULL pointer in %s:%d\n",
466 func, file, line);
467 return NULL;
468 }
469
470 n = q[0];
471 s = (char *) q;
472
474 XLALPrintError("%s meminfo: freeing %zu bytes at address %p in %s:%d\n",
475 func, n, p, file, line);
476 }
477
478 if (n == (size_t)(-1)) {
479 lalRaiseHook(SIGSEGV,
480 "%s error: tried to free a freed pointer at address %p in %s:%d\n",
481 func, p, file, line);
482 return NULL;
483 }
484
485 if (q[1] != magic) {
486 lalRaiseHook(SIGSEGV,
487 "%s error: wrong magic for pointer at address %p in %s:%d\n",
488 func, p, file, line);
489 return NULL;
490 }
491
492 if (((long) n) < 0) {
493 lalRaiseHook(SIGSEGV,
494 "%s error: corrupt size descriptor for pointer at address %p in %s:%d\n",
495 func, p, file, line);
496 return NULL;
497 }
498
499 /* check for writing past end of array: */
500 for (i = n; i < padFactor * n; ++i) {
501 if (s[i + prefix] != (char) (i ^ padding)) {
502 lalRaiseHook(SIGSEGV, "%s error: array bounds overwritten\n"
503 "Byte %ld past end of array has changed\n"
504 "Corrupted address: %p\nArray address: %p\n"
505 "Location: %s:%d\n",
506 func, i - n + 1, s + i + prefix, s + prefix, file, line);
507 return NULL;
508 }
509 }
510
511 /* see if there is enough allocated memory to be freed */
512 if (lalMallocTotal < n) {
513 lalRaiseHook(SIGSEGV, "%s error: lalMallocTotal too small\n",
514 func);
515 return NULL;
516 }
517
518 /* repad the memory */
519 for (i = keep ? n : 0; i < padFactor * n; ++i) {
520 s[i + prefix] = (char) (i ^ repadding);
521 }
522
523 q[0] = -1; /* set negative to detect duplicate frees */
524 q[1] = ~magic;
525
526 pthread_mutex_lock(&mut);
527 lalMallocTotal -= n;
529
530 return q;
531}
532
533
534static void *PushAlloc(void *p, size_t n, const char *file, int line)
535{
536 struct allocNode *newnode;
537 if (!(lalDebugLevel & LALMEMTRKBIT)) {
538 return p;
539 }
540 if (!p) {
541 return NULL;
542 }
543 if (!(newnode = malloc(sizeof(*newnode)))) {
544 return NULL;
545 }
546 pthread_mutex_lock(&mut);
547 newnode->addr = p;
548 newnode->size = n;
549 newnode->file = file;
550 newnode->line = line;
551 if (!AllocHashTblAdd(newnode)) {
552 free(newnode);
553 return NULL;
554 }
556 return p;
557}
558
559
560static void *PopAlloc(void *p, const char *func, const char *file, int line)
561{
562 if (!(lalDebugLevel & LALMEMTRKBIT)) {
563 return p;
564 }
565 if (!p) {
566 return NULL;
567 }
568 pthread_mutex_lock(&mut);
569 struct allocNode key = { .addr = p };
570 struct allocNode *node = AllocHashTblExtract(&key);
571 if (node == NULL) {
573 lalRaiseHook(SIGSEGV, "%s error: alloc %p not found\n"
574 "Location: %s:%d\n",
575 func, p, file, line);
576 return NULL;
577 }
578 free(node);
580 return p;
581}
582
583
584static void *ModAlloc(void *p, void *q, size_t n, const char *func,
585 const char *file, int line)
586{
587 if (!(lalDebugLevel & LALMEMTRKBIT)) {
588 return q;
589 }
590 if (!p || !q) {
591 return NULL;
592 }
593 pthread_mutex_lock(&mut);
594 struct allocNode key = { .addr = p };
595 struct allocNode *node = AllocHashTblExtract(&key);
596 if (node == NULL) {
598 lalRaiseHook(SIGSEGV, "%s error: alloc %p not found\n"
599 "Location: %s:%d\n",
600 func, p, file, line);
601 return NULL;
602 }
603 node->addr = q;
604 node->size = n;
605 node->file = file;
606 node->line = line;
607 if (!AllocHashTblAdd(node)) {
608 free(node);
609 return NULL;
610 }
612 return q;
613}
614
615
616
617void *LALMallocShort(size_t n)
618{
619 return (lalDebugLevel & LALMEMDBGBIT) ? LALMallocLong(n, "unknown", -1) : malloc(n);
620}
621
622
623
624void *LALMallocLong(size_t n, const char *file, int line)
625{
626 void *p;
627 void *q;
628
629 if (!(lalDebugLevel & LALMEMDBGBIT)) {
630 return malloc(n);
631 }
632
633 p = malloc(allocsz(n));
634 q = PushAlloc(PadAlloc(p, n, 0, "LALMalloc", file, line), n, file, line);
637 if (!q) {
638 XLALPrintError("LALMalloc: failed to allocate %zd bytes of memory\n", n);
639 XLALPrintError("LALMalloc: %zd bytes of memory already allocated\n", lalMallocTotal);
641 XLALPrintError("LALMalloc meminfo: out of memory\n");
642 }
643 if (p) {
644 free(p);
645 }
646 }
647 return q;
648}
649
650
651
652void *LALCallocShort(size_t m, size_t n)
653{
654 return (lalDebugLevel & LALMEMDBGBIT) ? LALCallocLong(m, n, "unknown", -1) :
655 calloc(m, n);
656}
657
658
659
660void *LALCallocLong(size_t m, size_t n, const char *file, int line)
661{
662 size_t sz;
663 void *p;
664 void *q;
665
666 if (!(lalDebugLevel & LALMEMDBGBIT)) {
667 return calloc(m, n);
668 }
669
670 sz = m * n;
671 p = malloc(allocsz(sz));
672 q = PushAlloc(PadAlloc(p, sz, 1, "LALCalloc", file, line), sz, file, line);
675 if (!q) {
676 XLALPrintError("LALMalloc: failed to allocate %zd bytes of memory\n", n);
677 XLALPrintError("LALMalloc: %zd bytes of memory already allocated\n", lalMallocTotal);
679 XLALPrintError("LALCalloc meminfo: out of memory\n");
680 }
681 if (p) {
682 free(p);
683 }
684 }
685 return q ? memset(q, 0, sz) : NULL;
686}
687
688
689
690void *LALReallocShort(void *p, size_t n)
691{
692 return (lalDebugLevel & LALMEMDBGBIT) ? LALReallocLong(p, n, "unknown", -1): realloc(p, n);
693}
694
695
696
697void *LALReallocLong(void *q, size_t n, const char *file, const int line)
698{
699 void *p;
700 if (!(lalDebugLevel & LALMEMDBGBIT)) {
701 return realloc(q, n);
702 }
703
706 if (!q) {
707 p = malloc(allocsz(n));
708 q = PushAlloc(PadAlloc(p, n, 0, "LALRealloc", file, line), n, file, line);
709 if (!q) {
710 XLALPrintError("LALMalloc: failed to allocate %zd bytes of memory\n", n);
711 XLALPrintError("LALMalloc: %zd bytes of memory already allocated\n", lalMallocTotal);
713 XLALPrintError("LALRealloc meminfo: out of memory\n");
714 }
715 if (p) {
716 free(p);
717 }
718 }
719 return q;
720 }
721
722 if (!n) {
723 p = UnPadAlloc(PopAlloc(q, "LALRealloc", file, line), 0, "LALRealloc", file, line);
724 if (p) {
725 free(p);
726 }
727 return NULL;
728 }
729
730 p = UnPadAlloc(q, 1, "LALRealloc", file, line);
731 if (!p) {
732 return NULL;
733 }
734
735 q = ModAlloc(q, PadAlloc(realloc(p, allocsz(n)), n, 1, "LALRealloc", file, line), n, "LALRealloc", file, line);
738
739 return q;
740}
741
742
743
744/* To avoid a backward-incompatible API change, LALFree() is still available as
745 * a function, so that any dependent libraries that expect to find a function
746 * LALFree() in liblal.so will do so. This function is not declared in
747 * LALMalloc.h, however, which now defines LALFree() as a macro.
748 */
749/** \cond DONT_DOXYGEN */
750void (LALFree)(void *q);
751void (LALFree)(void *q)
752{
754 return;
755}
756/** \endcond */
757
758void LALFreeShort(void *q)
759{
760 LALFreeLong(q, "unknown", -1);
761 return;
762}
763
764void LALFreeLong(void *q, const char *file, const int line)
765{
766 void *p;
767 if (q == NULL)
768 return;
769 if (!(lalDebugLevel & LALMEMDBGBIT)) {
770 free(q);
771 return;
772 }
775 p = UnPadAlloc(PopAlloc(q, "LALFree", file, line), 0, "LALFree", file, line);
776 if (p) {
777 free(p);
778 }
779 return;
780}
781
782
783
785{
786 int leak = 0;
787 if (!(lalDebugLevel & LALMEMDBGBIT)) {
788 return;
789 }
790
791 /* alloc_data_len should be zero */
793 XLALPrintError("LALCheckMemoryLeaks: allocation list\n");
794 for (int k = 0; k < alloc_data_len; ++k) {
795 if (alloc_data[k] != NULL && alloc_data[k] != DEL) {
796 XLALPrintError("%p: %zu bytes (%s:%d)\n", alloc_data[k]->addr,
798 alloc_data[k]->line);
799 }
800 }
801 leak = 1;
802 }
803
804 /* lalMallocTotal and alloc_n should be zero */
806 XLALPrintError("LALCheckMemoryLeaks: %d allocs, %zd bytes\n", alloc_n, lalMallocTotal);
807 leak = 1;
808 }
809
810 if (leak) {
811 lalRaiseHook(SIGSEGV, "LALCheckMemoryLeaks: memory leak\n");
812 } else if (lalDebugLevel & LALMEMINFOBIT) {
814 ("LALCheckMemoryLeaks meminfo: no memory leaks detected\n");
815 }
816
817 return;
818}
819
820#else /* LAL_MEMORY_FUNCTIONS_DISABLED */
821
822void (LALCheckMemoryLeaks)(void) { return; }
823
824#endif /* !LAL_MEMORY_FUNCTIONS_DISABLED */
int(* lalRaiseHook)(int, const char *,...)
Definition: LALError.c:57
static UNUSED struct allocNode * AllocHashTblExtract(struct allocNode *x)
Definition: LALMalloc.c:362
int lalIsMemDbgRetPtr
Definition: LALMalloc.c:251
#define EQUAL(x, y)
Definition: LALMalloc.c:287
static const size_t padFactor
Definition: LALMalloc.c:257
static UNUSED int AllocHashTblResize(void)
Definition: LALMalloc.c:297
#define INCRIDX(i)
Definition: LALMalloc.c:284
static void * ModAlloc(void *p, void *q, size_t n, const char *func, const char *file, int line)
Definition: LALMalloc.c:584
#define XLAL_TEST_POINTER(ptr, size)
Definition: LALMalloc.c:47
@ nprefix
Definition: LALMalloc.c:255
char * lalMemDbgRetPtr
Definition: LALMalloc.c:246
char * lalMemDbgArgPtr
Definition: LALMalloc.c:245
static int alloc_q
Definition: LALMalloc.c:274
static UNUSED struct allocNode * AllocHashTblFind(struct allocNode *x)
Definition: LALMalloc.c:324
int lalIsMemDbgArgPtr
Definition: LALMalloc.c:250
char * lalMemDbgUsrPtr
Definition: LALMalloc.c:248
void XLALFreeLong(void *p, const char *file UNUSED, int line UNUSED)
Definition: LALMalloc.c:120
#define HASHIDX(x)
Definition: LALMalloc.c:281
static UNUSED struct allocNode * FindAlloc(void *p)
Definition: LALMalloc.c:411
static const size_t prefix
Definition: LALMalloc.c:256
#define XLAL_TEST_POINTER_ALIGNED_LONG(ptr, size, retval, file, line)
Definition: LALMalloc.c:62
static void * UnPadAlloc(void *p, int keep, const char *func, const char *file, int line)
Definition: LALMalloc.c:453
static void * PadAlloc(size_t *p, size_t n, int keep, const char *func, const char *file, int line)
Definition: LALMalloc.c:418
static UNUSED int CheckAllocList(void)
Definition: LALMalloc.c:395
static int alloc_n
Definition: LALMalloc.c:273
#define pthread_mutex_lock(pmut)
Definition: LALMalloc.c:237
void ** lalMemDbgUsrHndl
Definition: LALMalloc.c:249
static struct allocNode ** alloc_data
int lalIsMemDbgPtr
Definition: LALMalloc.c:252
#define allocsz(n)
Definition: LALMalloc.c:262
static int alloc_data_len
Definition: LALMalloc.c:272
static void * PushAlloc(void *p, size_t n, const char *file, int line)
Definition: LALMalloc.c:534
static const size_t repadding
Definition: LALMalloc.c:259
static const void * hash_del
Definition: LALMalloc.c:277
static UNUSED int AllocHashTblAdd(struct allocNode *x)
Definition: LALMalloc.c:341
#define pthread_mutex_unlock(pmut)
Definition: LALMalloc.c:238
static const size_t magic
Definition: LALMalloc.c:260
void LALCheckMemoryLeaks(void)
Definition: LALMalloc.c:784
#define DEL
Definition: LALMalloc.c:278
static void * PopAlloc(void *p, const char *func, const char *file, int line)
Definition: LALMalloc.c:560
#define XLAL_TEST_POINTER_LONG(ptr, size, file, line)
Definition: LALMalloc.c:51
char * lalMemDbgPtr
Definition: LALMalloc.c:247
static const size_t padding
Definition: LALMalloc.c:258
#define XLAL_TEST_POINTER_ALIGNED(ptr, size, retval)
Definition: LALMalloc.c:58
#define LALFree(p)
Definition: LALMalloc.h:96
int XLALPrintError(const char *fmt,...)
Definition: XLALError.c:68
#define lalDebugLevel
Definition: LALDebugLevel.h:58
@ 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
void * LALReallocShort(void *p, size_t n)
Definition: LALMalloc.c:690
void LALFreeShort(void *q)
Definition: LALMalloc.c:758
void * XLALMallocLong(size_t n, const char *file, int line)
Definition: LALMalloc.c:77
void * LALCallocLong(size_t m, size_t n, const char *file, int line)
Definition: LALMalloc.c:660
void LALFreeLong(void *q, const char *file, const int line)
Definition: LALMalloc.c:764
size_t lalMallocTotalPeak
peak amount of memory allocated so far
Definition: LALMalloc.c:39
void *() XLALMalloc(size_t n)
Definition: LALMalloc.c:70
void * LALReallocLong(void *q, size_t n, const char *file, const int line)
Definition: LALMalloc.c:697
void *() XLALCalloc(size_t m, size_t n)
Definition: LALMalloc.c:85
void * XLALReallocLong(void *p, size_t n, const char *file, int line)
Definition: LALMalloc.c:106
void * XLALCallocLong(size_t m, size_t n, const char *file, int line)
Definition: LALMalloc.c:92
size_t lalMallocTotal
current amount of memory allocated by process
Definition: LALMalloc.c:38
void * LALCallocShort(size_t m, size_t n)
Definition: LALMalloc.c:652
void *() XLALRealloc(void *p, size_t n)
Definition: LALMalloc.c:100
void * LALMallocShort(size_t n)
Definition: LALMalloc.c:617
void * LALMallocLong(size_t n, const char *file, int line)
Definition: LALMalloc.c:624
void() XLALFree(void *p)
Definition: LALMalloc.c:113
static const INT4 m
Definition: Random.c:80
static const INT4 q
Definition: Random.c:81
const char * file
Definition: LALMalloc.c:269
size_t size
Definition: LALMalloc.c:268
int line
Definition: LALMalloc.c:270
void * addr
Definition: LALMalloc.c:267