Provides standard LAL memory allocation/deallocation routines.
This header covers routines that replace the standard malloc()
, calloc()
, realloc()
, and free()
. All memory allocation and deallocation in LAL should use these replacement functions. If the LAL_MEMORY_FUNCTIONS_DISABLED
flag is set in LALConfig.h, the LAL routines are #define
d to be the same as the standard C routines.
LALxxx()
interface is deprecated, it is recommended to use the corresponding XLALxxx() functions instead, which follow exactly the same API as the functions described in the following.These functions are the LAL replacements for malloc()
, calloc()
, realloc()
, and free()
, with extra functionality to check for memory leaks (i.e. unfreed memory and segmentation violations). The LALMallocLong()
, LALCallocLong()
, and LALReallocLong()
functions have two extra arguments giving the file name and line number of the calling statement; LALMallocShort()
, LALCallocShort()
, and LALReallocShort()
do not have these extra arguments, and are merely call the corresponding long alloc functions with a file name of "unknown"
and a line number of -1
(they are useful if you want to replace hooks to malloc()
, calloc()
, and realloc()
of an external package that provides suitable hooks). LALMalloc()
, LALCalloc()
, and LALRealloc()
are actually macros which call the functions LALMallocLong()
, LALCallocLong()
, and LALReallocLong
with the appropriate file name and line number information. In practice, it is almost sufficient to use LALMalloc()
, LALCalloc()
, and LALRealloc()
as you would malloc()
, calloc()
, and realloc()
.
Any time an object is freed, LALFree()
checks to make sure that the memory bounds were not over-written, and that the memory address is valid. The function LALCheckMemoryLeaks()
is to be called at the end of a program when all the allocated memory is expected to have been freed. If there is memory that has been allocated but not freed then this routine reports an error. Whenever a memory leak is detected, the routines raise a segmentation violation signal SIGSEGV
. (The signal is raised using the signal raising hook lalRaiseHook
, which can be reset to a different handler if desired.)
Memory leak detection adds significant computational overhead to a program. It also requires the use of static memory, making the code non-thread-safe (but it can be made posix-thread-safe using the –enable-pthread-lock
configure option). Production code should suppress memory leak detection at runtime by setting the global lalDebugLevel
equal to zero or by setting the LALNMEMDBG
bit of lalDebugLevel
. In addition, you can turn off individual components of the memory debugging tools. Setting the LALNMEMPAD
bit of lalDebugLevel
prevents the allocation routines from "padding out" the arrays in an effort to detect buffer overflows. Setting the LALNMEMTRK
bit of lalDebugLevel
prevents tracking the allocations/frees. Setting the LALMEMINFO
bit of lalDebugLevel
produces copious output describing each memory allocation and deallocation.
If one wishes to completely disable the LAL routines, one can configure LAL with the –disable-memory-functions
option, which sets the LAL_MEMORY_FUNCTIONS_DISABLED
flag in LALConfig.h. This causes LALCheckMemoryLeaks()
to do nothing, and the other functions to revert to their standard C counterparts.
When buffer overflow detection is active, LALMalloc()
allocates, in addition to the requested memory, storage at the beginning of the object where a magic number and the size of the object is recorded, and padding at the end of the object. The number of allocations and the total size of allocated memory are stored in static memory. When LALFree()
is executed, the padding at the end of the object and the magic number are examined to see if the bounds of the object were over-written. The total number of allocations and the total memory allocated are decreased. LALCheckMemoryLeaks()
is called when all memory should have been freed. If the number of allocations or the total memory allocated is not zero, this routine reports an error.
When memory tracking is active, LALMalloc()
keeps a linked list containing information about each allocation: the memory address, the size of the allocation, and the file name and line number of the calling statement. Subsequent calls to LALFree()
make sure that the address to be freed was correctly allocated. In addition, in the case of a memory leak in which some memory that was allocated was not freed, LALCheckMemoryLeaks()
prints a list of all allocations and the information about the allocations.
When any of these routines encounter an error, they will issue an error message using LALPrintError()
and will raise a SIGSEGV
signal, which will normally cause execution to terminate. The signal is raised using the hook lalRaiseHook
, which can be set to perform a different action if desired.
These routines also issue status messages indicating how much memory is being allocated or freed with each function call. These memory information messages are considered a distinct class of status message, and can be activated or suppressed independently of other status messages. See the discussion in LALStatusMacros.h.
When lalDebugLevel
is set to zero or the LALNMEMDBG
bit is set, or when compiled with the LAL_MEMORY_FUNCTIONS_DISABLED
flag set, these functions revert to their standard system versions, and LALCheckMemoryLeaks()
does nothing.
Memory leak detection only occurs when lalDebugLevel
\(\neq0\). To turn on leak detection independent of error reporting, simply switch on the most-significant bit of lalDebugLevel
, which is reserved not to be associated with any type of status message. See the discussion in LALStatusMacros.h for more information about lalDebugLevel
.
It is assumed that pointers of type size_t *
have the most restrictive alignment. If this is not true, then this code may not work except in non-debugging mode. (It will probably produce bus errors.)
Programs should end by calling LALCheckMemoryLeaks()
. This will ensure that all memory that has been allocated has been freed. Making sure that all memory allocated is freed is a good idea in order to make sure (i) that memory isn't being "lost" (which may mean that the computer will run out of memory when the program is run under more extensive use), (ii) that array bounds are not being exceeded (since this will usually overwrite the pad area at the end of the array, and this overwrite is detected when the array is freed). LALCheckMemoryLeaks()
should pass silently—if it doesn't, then there is probably some memory that has not been freed; LALCheckMemoryLeaks()
will give information about where this memory was allocated.
The most common problem (after forgetting to free some memory) is overwriting of array bounds. When this is detected, LALFree()
reports the memory address that was overwritten, as well as the address of the array that LALFree()
attempted to free. In order to find out where the overwrite occurs, run the program in the debugger and stop the execution as soon as the array that is being overwritten has been allocated. The LALMalloc
module has some secret memory debugging tools (for use in debugging only!). One is the global variable lalMemDbgUsrPtr
, which is of type char *
. Set this variable to be equal to the memory address where the overwrite occurs. Then watch the contents of the variable to find out where the overwrite occurs. This is done in gdb
using the commands:
where 0x20f530
is the corrupted memory address. The program will run until the value of this address is changed, thereby allowing you to find out where in the program the overwrite occurs.
If you don't know where the memory was allocated, you can locate this too. To do so, set lalMemDbgUsrPtr
to be the address of the array. Then, every time LALMalloc()
is called, it sets the value of the global variable lalIsMemDbgRetPtr
to be one zero if the array address produced by LALMalloc()
is not the address in lalMemDbgUsrPtr
, and one if it is. Then you can watch the value of lalIsMemDbgRetPtr
in a debugger until it changes to one, which stops execution at that point. (Note: it is possible that a given address is allocated, then freed, the allocated again—you may need to watch lalIsMemDbgRetPtr
for a while.)
Here's an example debugging session: first we run the program, identify the address of the array whose bounds are being overwritten, and find out where that array is allocated.
So here is where the memory is allocated. We want to find out where the memory is being corrupted.
Notice that the program has stopped just after the line in which the array bounds were overwritten.
Prototypes | |
void * | XLALMalloc (size_t n) |
void * | XLALMallocLong (size_t n, const char *file, int line) |
void * | XLALCalloc (size_t m, size_t n) |
void * | XLALCallocLong (size_t m, size_t n, const char *file, int line) |
void * | XLALRealloc (void *p, size_t n) |
void * | XLALReallocLong (void *p, size_t n, const char *file, int line) |
void | XLALFree (void *p) |
void | XLALFreeLong (void *p, const char *file, const int line) |
void * | LALMallocShort (size_t n) |
void * | LALMallocLong (size_t n, const char *file, int line) |
void * | LALCallocShort (size_t m, size_t n) |
void * | LALCallocLong (size_t m, size_t n, const char *file, int line) |
void * | LALReallocShort (void *p, size_t n) |
void * | LALReallocLong (void *p, size_t n, const char *file, int line) |
void | LALFreeShort (void *p) |
void | LALFreeLong (void *p, const char *file, int line) |
Macros | |
#define | XLALMalloc(n) XLALMallocLong( n, __FILE__, __LINE__ ) |
#define | XLALCalloc(m, n) XLALCallocLong( m, n, __FILE__, __LINE__ ) |
#define | XLALRealloc(p, n) XLALReallocLong( p, n, __FILE__, __LINE__ ) |
#define | XLALFree(p) XLALFreeLong( p, __FILE__, __LINE__ ) |
Files | |
file | LALMallocPerf.c |
Tests the performance of the routines in Header LALMalloc.h. | |
file | LALMallocTest.c |
Tests the routines in Header LALMalloc.h. | |
Variables | |
size_t | lalMallocTotal |
current amount of memory allocated by process More... | |
size_t | lalMallocTotalPeak |
peak amount of memory allocated so far More... | |
void * XLALMalloc | ( | size_t | n | ) |
Definition at line 70 of file LALMalloc.c.
void * XLALMallocLong | ( | size_t | n, |
const char * | file, | ||
int | line | ||
) |
Definition at line 77 of file LALMalloc.c.
void * XLALCalloc | ( | size_t | m, |
size_t | n | ||
) |
Definition at line 85 of file LALMalloc.c.
void * XLALCallocLong | ( | size_t | m, |
size_t | n, | ||
const char * | file, | ||
int | line | ||
) |
Definition at line 92 of file LALMalloc.c.
void * XLALRealloc | ( | void * | p, |
size_t | n | ||
) |
Definition at line 100 of file LALMalloc.c.
void * XLALReallocLong | ( | void * | p, |
size_t | n, | ||
const char * | file, | ||
int | line | ||
) |
Definition at line 106 of file LALMalloc.c.
void XLALFree | ( | void * | p | ) |
Definition at line 113 of file LALMalloc.c.
void XLALFreeLong | ( | void * | p, |
const char * | file, | ||
const int | line | ||
) |
void * LALMallocShort | ( | size_t | n | ) |
Definition at line 617 of file LALMalloc.c.
void * LALMallocLong | ( | size_t | n, |
const char * | file, | ||
int | line | ||
) |
Definition at line 624 of file LALMalloc.c.
void * LALCallocShort | ( | size_t | m, |
size_t | n | ||
) |
Definition at line 652 of file LALMalloc.c.
void * LALCallocLong | ( | size_t | m, |
size_t | n, | ||
const char * | file, | ||
int | line | ||
) |
Definition at line 660 of file LALMalloc.c.
void * LALReallocShort | ( | void * | p, |
size_t | n | ||
) |
Definition at line 690 of file LALMalloc.c.
void * LALReallocLong | ( | void * | p, |
size_t | n, | ||
const char * | file, | ||
int | line | ||
) |
Definition at line 697 of file LALMalloc.c.
void LALFreeShort | ( | void * | p | ) |
Definition at line 758 of file LALMalloc.c.
void LALFreeLong | ( | void * | p, |
const char * | file, | ||
int | line | ||
) |
Definition at line 764 of file LALMalloc.c.
#define XLALMalloc | ( | n | ) | XLALMallocLong( n, __FILE__, __LINE__ ) |
Definition at line 44 of file LALMalloc.h.
#define XLALCalloc | ( | m, | |
n | |||
) | XLALCallocLong( m, n, __FILE__, __LINE__ ) |
Definition at line 45 of file LALMalloc.h.
#define XLALRealloc | ( | p, | |
n | |||
) | XLALReallocLong( p, n, __FILE__, __LINE__ ) |
Definition at line 46 of file LALMalloc.h.
#define XLALFree | ( | p | ) | XLALFreeLong( p, __FILE__, __LINE__ ) |
Definition at line 47 of file LALMalloc.h.
|
extern |
current amount of memory allocated by process
Definition at line 38 of file LALMalloc.c.
|
extern |
peak amount of memory allocated so far
Definition at line 39 of file LALMalloc.c.