The Memory Management Library  0.2.1
Functions | Variables
memoryd.c File Reference

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"
Include dependency graph for memoryd.c:

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.

Detailed Description

Source for Memory Management Library - Debugging Version (CBL)


Function Documentation

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

Parameters:
[in]nsize of memory block requested in bytes
[in]filefile name in which allocation requested
[in]funcfunction name in which allocation requested (if C99 supported)
[in]linelinu number on which allocation requested
Returns:
memory block 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

Parameters:
[in]cnumber of items to be allocated
[in]nsize in bytes for one item
[in]filefile name in which allocation requested
[in]funcfunction name in which allocation requested (if C99 supported)
[in]lineline number on which allocation requested
Returns:
pointer to allocated (zero-filled) memory block
Todo:
Improvements are possible and planned:
  • the C standard requires calloc() return a null pointer if it can allocates no storage of the size c * n in bytes, which allows no overflow in computing the multiplication. Overflow checking is necessary to mimic the behavior of calloc().

Here is the call graph for this function:

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

Parameters:
[in]ppointer to memory block to release (to mark as "freed")
[in]filefile name in which deallocation requested
[in]funcfunction name in which deallocation requested (if C99 supported)
[in]lineline number on which deallocation is requested
Returns:
nothing

Here is the call graph for this function:

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

Parameters:
[in]applyuser-provided function to be called for each memory block in use
[in]clpassing-by argument to apply
Returns:
nothing
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

Parameters:
[in]fpfile to which log message printed out
[in]freefuncuser-provided function to log free-free case; default message used when null pointer given
[in]resizefuncuser-provided function to log resize-free case; default message used when null pointer given
Returns:
nothing
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

Parameters:
[in]ppointer to memory block whose size to be adjusted
[in]nnew size for memory block in bytes
[in]filefile name in which adjustment requested
[in]funcfunction name in which adjustment requested (if C99 supported)
[in]lineline number on which adjustment requested
Returns:
pointer to size-adjusted memory block

Here is the call graph for this function:

 All Data Structures Files Functions Variables Typedefs Defines