LAL  7.5.0.1-8083555
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 */
38 size_t lalMallocTotal = 0; /**< current amount of memory allocated by process */
39 size_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 
70 void *(XLALMalloc) (size_t n) {
71  void *p;
72  p = LALMallocShort(n);
73  XLAL_TEST_POINTER(p, n);
74  return p;
75 }
76 
77 void *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 
85 void *(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 
92 void *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 
100 void *(XLALRealloc) (void *p, size_t n) {
101  p = LALReallocShort(p, n);
102  XLAL_TEST_POINTER(p, n);
103  return p;
104 }
105 
106 void *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 
113 void (XLALFree) (void *p)
114 {
115  if (p)
116  LALFreeShort(p);
117  return;
118 }
119 
120 void 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 
137 int XLALIsMemoryAligned(void *ptr)
138 {
139  return LAL_IS_MEMORY_ALIGNED(ptr);
140 }
141 
142 void *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 
151 void *(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 
160 void *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 
169 void *(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 
178 void *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 
197 void *(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 
216 void 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>
235 static 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 */
245 char *lalMemDbgArgPtr = NULL; /* set to ptr arg in free or realloc */
246 char *lalMemDbgRetPtr = NULL; /* set to ptr returned in alloc functions */
247 char *lalMemDbgPtr = NULL; /* set in both cases */
248 char *lalMemDbgUsrPtr = NULL; /* avaliable global memory pointer for user */
249 void **lalMemDbgUsrHndl = NULL; /* avaliable global memory handle for user */
250 int lalIsMemDbgArgPtr; /* ( lalMemDbgUsrPtr == lalMemDbgArgPtr ) */
251 int lalIsMemDbgRetPtr; /* ( lalMemDbgUsrPtr == lalMemDbgRetPtr ) */
252 int lalIsMemDbgPtr; /* ( lalMemDbgUsrPtr == lalMemDbgPtr ) */
253 
254 
255 enum { nprefix = 2 };
256 static const size_t prefix = nprefix * sizeof(size_t);
257 static const size_t padFactor = 2;
258 static const size_t padding = 0xDeadBeef;
259 static const size_t repadding = 0xBeefDead;
260 static 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 
266 static 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 */
272 static int alloc_data_len = 0; /* Size of the memory block 'alloc_data', in number of elements */
273 static int alloc_n = 0; /* Number of valid elements in the hash */
274 static 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 */
277 static 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 */
297 UNUSED 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  }
309  alloc_q = alloc_n;
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 */
324 UNUSED 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 */
341 UNUSED 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 */
362 UNUSED 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 */
395 UNUSED 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 */
411 UNUSED static struct allocNode *FindAlloc(void *p)
412 {
413  struct allocNode key = { .addr = p };
414  return AllocHashTblFind(&key);
415 }
416 
417 
418 static 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;
447  pthread_mutex_unlock(&mut);
448 
449  return (void *) (((char *) p) + prefix);
450 }
451 
452 
453 static 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;
528  pthread_mutex_unlock(&mut);
529 
530  return q;
531 }
532 
533 
534 static 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  }
555  pthread_mutex_unlock(&mut);
556  return p;
557 }
558 
559 
560 static 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) {
572  pthread_mutex_unlock(&mut);
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);
579  pthread_mutex_unlock(&mut);
580  return p;
581 }
582 
583 
584 static 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) {
597  pthread_mutex_unlock(&mut);
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  }
611  pthread_mutex_unlock(&mut);
612  return q;
613 }
614 
615 
616 
617 void *LALMallocShort(size_t n)
618 {
619  return (lalDebugLevel & LALMEMDBGBIT) ? LALMallocLong(n, "unknown", -1) : malloc(n);
620 }
621 
622 
623 
624 void *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 
652 void *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 
660 void *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 
690 void *LALReallocShort(void *p, size_t n)
691 {
692  return (lalDebugLevel & LALMEMDBGBIT) ? LALReallocLong(p, n, "unknown", -1): realloc(p, n);
693 }
694 
695 
696 
697 void *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 */
750 void (LALFree)(void *q);
751 void (LALFree)(void *q)
752 {
753  LALFreeShort(q);
754  return;
755 }
756 /** \endcond */
757 
758 void LALFreeShort(void *q)
759 {
760  LALFreeLong(q, "unknown", -1);
761  return;
762 }
763 
764 void 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 */
792  if ((lalDebugLevel & LALMEMTRKBIT) && alloc_data_len > 0) {
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,
797  alloc_data[k]->size, alloc_data[k]->file,
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 
822 void (LALCheckMemoryLeaks)(void) { return; }
823 
824 #endif /* !LAL_MEMORY_FUNCTIONS_DISABLED */
int(* lalRaiseHook)(int, const char *,...)
Definition: LALError.c:57
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
#define XLAL_TEST_POINTER(ptr, size)
Definition: LALMalloc.c:47
char * lalMemDbgRetPtr
Definition: LALMalloc.c:246
char * lalMemDbgArgPtr
Definition: LALMalloc.c:245
static UNUSED struct allocNode * AllocHashTblFind(struct allocNode *x)
Definition: LALMalloc.c:324
static int alloc_q
Definition: LALMalloc.c:274
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
static UNUSED struct allocNode * AllocHashTblExtract(struct allocNode *x)
Definition: LALMalloc.c:362
#define HASHIDX(x)
Definition: LALMalloc.c:281
static void * ModAlloc(void *p, void *q, size_t n, const char *func, const char *file, int line)
Definition: LALMalloc.c:584
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 * 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 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
@ nprefix
Definition: LALMalloc.c:255
#define pthread_mutex_unlock(pmut)
Definition: LALMalloc.c:238
static void * UnPadAlloc(void *p, int keep, const char *func, const char *file, int line)
Definition: LALMalloc.c:453
static const size_t magic
Definition: LALMalloc.c:260
void LALCheckMemoryLeaks(void)
Definition: LALMalloc.c:784
static void * PushAlloc(void *p, size_t n, const char *file, int line)
Definition: LALMalloc.c:534
#define DEL
Definition: LALMalloc.c:278
#define XLAL_TEST_POINTER_LONG(ptr, size, file, line)
Definition: LALMalloc.c:51
char * lalMemDbgPtr
Definition: LALMalloc.c:247
static void * PopAlloc(void *p, const char *func, const char *file, int line)
Definition: LALMalloc.c:560
static const size_t padding
Definition: LALMalloc.c:258
#define XLAL_TEST_POINTER_ALIGNED(ptr, size, retval)
Definition: LALMalloc.c:58
static UNUSED struct allocNode * FindAlloc(void *p)
Definition: LALMalloc.c:411
#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 LALFreeShort(void *q)
Definition: LALMalloc.c:758
void *() XLALCalloc(size_t m, size_t n)
Definition: LALMalloc.c:85
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 * XLALCallocLong(size_t m, size_t n, const char *file, int line)
Definition: LALMalloc.c:92
void * LALCallocShort(size_t m, size_t n)
Definition: LALMalloc.c:652
void * XLALReallocLong(void *p, size_t n, const char *file, int line)
Definition: LALMalloc.c:106
void * LALMallocLong(size_t n, const char *file, int line)
Definition: LALMalloc.c:624
void * LALCallocLong(size_t m, size_t n, const char *file, int line)
Definition: LALMalloc.c:660
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
size_t lalMallocTotal
current amount of memory allocated by process
Definition: LALMalloc.c:38
void *() XLALRealloc(void *p, size_t n)
Definition: LALMalloc.c:100
void * XLALMallocLong(size_t n, const char *file, int line)
Definition: LALMalloc.c:77
void * LALReallocShort(void *p, size_t n)
Definition: LALMalloc.c:690
void * LALMallocShort(size_t n)
Definition: LALMalloc.c:617
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