The Memory Management Library
0.2.1
|
Source for Memory Management Library - Debugging Version (CBL) More...
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "cbl/assert.h"
#include "cbl/except.h"
#include "memory.h"
Functions | |
void() | mem_free (void *p, const char *file, int line) |
deallocates a memory block. | |
void *() | mem_resize (void *p, size_t n, const char *file, int line) |
adjusts the size of a memory block pointed to by p to n . | |
void *() | mem_calloc (size_t c, size_t n, const char *file, int line) |
allocates a zero-filled memory block of the size c * n in bytes. | |
void *() | mem_alloc (size_t n, const char *file, int line) |
allocates a new memory block of the size n in bytes. | |
void() | mem_log (FILE *fp, void freefunc(FILE *, const mem_loginfo_t *), void resizefunc(FILE *, const mem_loginfo_t *)) |
starts to log invalid memory usage. | |
void() | mem_leak (void apply(const mem_loginfo_t *, void *), void *cl) |
calls a user-provided function for each memory block in use. | |
Variables | |
const except_t | mem_exceptfail = { "Allocation failed" } |
exception for memory allocation failure. |
Source for Memory Management Library - Debugging Version (CBL)
void*() mem_alloc | ( | size_t | n, |
const char * | file, | ||
int | line | ||
) |
allocates a new memory block of the size n
in bytes.
allocates storage of the size n
in bytes.
Some general explanation on mem_alloc() can be found on the production version of the library.
Possible exceptions: mem_exceptfail, assert_exceptfail
Unchecked errors: none
[in] | n | size of memory block requested in bytes |
[in] | file | file name in which allocation requested |
[in] | func | function name in which allocation requested (if C99 supported) |
[in] | line | linu number on which allocation requested |
void*() mem_calloc | ( | size_t | c, |
size_t | n, | ||
const char * | file, | ||
int | line | ||
) |
allocates a zero-filled memory block of the size c
* n
in bytes.
allocates zero-filled storage of the size c
* n
in bytes.
mem_calloc() returns a zero-filled memory block whose size is at least n
. mem_calloc() allocates a memory block by invoking mem_malloc() and set its every byte to zero by memset(). The similar explanation as for mem_alloc() applies to mem_calloc() too; see mem_alloc().
Possible exceptions: assert_exceptfail, mem_exceptfail
Unchecked errors: none
[in] | c | number of items to be allocated |
[in] | n | size in bytes for one item |
[in] | file | file name in which allocation requested |
[in] | func | function name in which allocation requested (if C99 supported) |
[in] | line | line number on which allocation requested |
c
* n
in bytes, which allows no overflow in computing the multiplication. Overflow checking is necessary to mimic the behavior of calloc(). void() mem_free | ( | void * | p, |
const char * | file, | ||
int | line | ||
) |
deallocates a memory block.
deallocates storage pointed to by p
.
mem_free() releases a given memory block.
Possible exceptions: assert_exceptfail
Unchecked errors: none
[in] | p | pointer to memory block to release (to mark as "freed") |
[in] | file | file name in which deallocation requested |
[in] | func | function name in which deallocation requested (if C99 supported) |
[in] | line | line number on which deallocation is requested |
void() mem_leak | ( | void | applyconst mem_loginfo_t *, void *, |
void * | cl | ||
) |
calls a user-provided function for each memory block in use.
mem_leak() is useful when detecting memory leakage. Before terminating a program, calling it with a callback function which are passed to apply
makes the callback function called with the information of every memory block still in use (or not deallocated). Among the member of mem_loginfo_t
, p
, size
, afile
, afunc
and aline
are filled; if some of them are unavailable, they are set to a null pointer for pointer members or 0 for integer members. An information that a user needs to give to a callback function can be passed through cl
. The following shows an example of a callback function:
void inuse(const mem_loginfo_t *loginfo, void *cl) { FILE *logfile = cl; const char *file, func; file = (loginfo->afile)? loginfo->afile: "unknown file"; func = (loginfo->afunc)? loginfo->afunc: "unknown function"; fprintf(logfile, "** memory in use at %p\n", loginfo->p); fprintf(logfile, "this block is %ld bytes long and was allocated from %s() %s:%d\n", (unsigned long)loginfo->size, func, file, loginfo->aline); fflush(logfile); }
If this callback function is invoked by calling mem_leak() as follows:
mem_leak(inuse, stderr);
it prints out a list of memory blocks still in use to stderr
as follows:
** memory in use at 0xfff7 this block is 2048 bytes long and was allocated from table_init() table.c:235
If a null pointer is given to apply
, the pre-defined internal callback function is invoked to print the information for memory leak to a file given through cl
(after converted to a pointer to FILE
). If cl
is also a null pointer, a file possibly set by mem_log() is inspected to see if it is available, before the information printed finally goes to stderr
.
Possible exceptions: none
Unchecked errors: invalid function pointer given for apply
, invalid file pointer given for cl
when apply
is given a null pointer
[in] | apply | user-provided function to be called for each memory block in use |
[in] | cl | passing-by argument to apply |
void() mem_log | ( | FILE * | fp, |
void | freefuncFILE *, const mem_loginfo_t *, | ||
void | resizefuncFILE *, const mem_loginfo_t * | ||
) |
starts to log invalid memory usage.
mem_log() starts to log invalid memory usage; deallocating an already released memory called "free-free" or "double free" and resizing a non-allocated memory called "resize-free" here. mem_log() provides two ways to log them. A user can register his/her own log function for the free-free or resize-free case by providing a function to freefunc
or resizefunc
. The necessary information is provided to the registered function via a mem_loginfo_t
object. A user-provided log function must be defined as follows:
void user_freefree(FILE *fp, const mem_loginfo_t *info) { ... }
See the explanation of mem_loginfo_t
for the information provided to a user-registered function. The file pointer given to mem_log()'s fp
is passed to the first parameter of an user-registered log function.
If freefunc
or resizefunc
are given a null pointer, the default log messages are printed to the file specified by fp
. The message looks like:
** freeing free memory mem_free(0x6418) called from table_mgr() table.c:461 this block is 48 bytes long and was allocated table_init() table.c:233 ** resizing unallocated memory mem_resize(0xf7ff, 640) called from table_mgr() table.c:468 this block is 32 bytes long and was allocated table_init() table.c:230
Invoking mem_log() with a null pointer for fp
stops logging.
Possible exceptions: none
Unchecked errors: invalid file pointer given for fp
, invalid function pointer given for freefunc
or resizefunc
[in] | fp | file to which log message printed out |
[in] | freefunc | user-provided function to log free-free case; default message used when null pointer given |
[in] | resizefunc | user-provided function to log resize-free case; default message used when null pointer given |
void*() mem_resize | ( | void * | p, |
size_t | n, | ||
const char * | file, | ||
int | line | ||
) |
adjusts the size of a memory block pointed to by p
to n
.
adjust the size of storage pointed to by p
to n
.
mem_resize() does the main job of realloc(); adjusting the size of the memory block already allocated by mem_alloc() or mem_calloc(). While realloc() deallocates like free() when the given size is 0 and allocates like malloc() when the given pointer is a null pointer, mem_resize() accepts neither a null pointer nor zero as its arguments. The similar explanation as for mem_alloc() also applies to mem_resize(). See mem_alloc() for details.
Possible exceptions: mem_exceptfail, assert_exceptfail
Unchecked errors: none
[in] | p | pointer to memory block whose size to be adjusted |
[in] | n | new size for memory block in bytes |
[in] | file | file name in which adjustment requested |
[in] | func | function name in which adjustment requested (if C99 supported) |
[in] | line | line number on which adjustment requested |