diff options
author | Michael Jennings <mej@lbl.gov> | 2013-03-22 17:10:10 -0700 |
---|---|---|
committer | Michael Jennings <mej@lbl.gov> | 2013-03-22 17:10:10 -0700 |
commit | aec69ba959f1ce3cb0cd87b2ba8fc786089dd521 (patch) | |
tree | 0e0fb6f76a4305de3b44bf7944b8a3abeb1f5a22 | |
parent | 9f1e27591d9f03d78af7ac3a9343a3782de0f2f4 (diff) | |
download | libast-devs/mej/malloc-tracking-removal.tar.gz |
Working on rewrite of memory subsystem.devs/mej/malloc-tracking-removal
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | include/libast.h | 321 | ||||
-rw-r--r-- | include/libast/sysdefs.h.in | 5 | ||||
-rw-r--r-- | libast.m4 | 64 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/mem.c | 760 |
6 files changed, 162 insertions, 992 deletions
diff --git a/configure.ac b/configure.ac index 167ed0d..9ea4deb 100644 --- a/configure.ac +++ b/configure.ac @@ -87,8 +87,6 @@ AC_TRY_RUN([ AC_MSG_RESULT([no - assumed because cross-compiling]) ]) -AST_X11_SUPPORT() -AST_IMLIB2_SUPPORT() AST_MMX_SUPPORT() AST_ARG_REGEXP(REGEXP) AST_ARG_BACKQUOTE_EXEC(ALLOW_BACKQUOTE_EXEC) diff --git a/include/libast.h b/include/libast.h index d966df3..d133be8 100644 --- a/include/libast.h +++ b/include/libast.h @@ -967,118 +967,6 @@ extern int re_exec(); /********************************* MEM GOOP ***********************************/ /** - * @def MALLOC(sz) - * Allocate @a sz bytes of memory. - * - * This macro is a replacement for the libc function malloc(). It - * allocates the specified number of bytes of memory on the heap and - * returns a pointer to that memory location. This macro calls libc's - * malloc() if memory debugging is off, and spifmem_malloc() if it's - * on. - * - * @param sz The size in bytes of the block of memory to allocate. - * @return A pointer to the allocated memory. - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink - * @ingroup DOXGRP_MEM - */ -/** - * @def CALLOC(type, n) - * Allocate enough memory for @a n objects of type @a type. - * - * This macro is a replacement for the libc function calloc(). It - * allocates a block of memory on the heap large enough to hold @a n - * objects of type @a type (e.g., a @a type array of size @a n). The - * memory area is zeroed out prior to the pointer to it being - * returned. This macro calls libc's calloc() if memory debugging is - * off and spifmem_calloc() if it's on. - * - * @param type The type of object to be allocated (e.g., int). - * @param n The number of objects to be allocated. - * @return A pointer to the allocated memory. - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink - * @ingroup DOXGRP_MEM - */ -/** - * @def REALLOC(mem, sz) - * Resize the memory block pointed to by @a mem to @a sz bytes. - * - * This macro is a replacement for the libc function realloc(). It - * changes the size of a chunk of memory previously allocated by - * malloc() or calloc() (or, by extension, the MALLOC()/CALLOC() - * macros) and returns a pointer to the (possibly moved) memory area. - * This macro calls libc's realloc() if memory debugging is off and - * spifmem_realloc() if it's on. - * - * @param mem The old pointer whose size will be changed. - * @param sz The new size, in bytes, to be allocated. - * @return The new pointer value, which may or may not differ from the - * old value. - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink - * @ingroup DOXGRP_MEM - */ -/** - * @def FREE(ptr) - * Free a previously-allocated memory block. - * - * This macro is a replacement for the libc function free(). It - * returns the previously-allocated memory block pointed to by @a ptr - * to the heap. This macro calls libc's free() if memory debugging is - * off and spifmem_free() if it's on. The @a ptr parameter is assigned - * the value of NULL after it has been freed. - * - * @param ptr The pointer to be freed. - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink - * @ingroup DOXGRP_MEM - */ -/** - * @def ALLOCA(sz) - * Allocate @a sz bytes of memory on the stack. - * - * This macro is a replacement for the libc function alloca(). It - * allocates the specified number of bytes of memory on the stack and - * returns a pointer to that memory location. This macro calls libc's - * alloca() if memory debugging is off, and wraps it if it's - * on. - * - * @param sz The size in bytes of the block of memory to allocate. - * @return A pointer to the allocated memory. - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink - * @ingroup DOXGRP_MEM - */ -/** - * @def STRDUP(s) - * Duplicate a string pointer and return a pointer to the new copy. - * - * This macro is a replacement for the libc function strdup(). It - * allocates a section of memory large enough to hold the string @a s - * (including the trailing NUL character), copies the contents of @a s - * into the new buffer, and returns a pointer to the new copy. This - * macro calls libc's strdup() of memory debugging is off and - * spifmem_strdup() if it's on. - * - * @param s The string to duplicate. - * @return A pointer to the newly-created copy. - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink - * @ingroup DOXGRP_MEM - */ -/** - * @def MALLOC_DUMP() - * Dumps a listing of all allocated pointers along with their sizes - * and contents in both hex and ASCII. - * - * This macro is used to view the status of memory allocated via the - * LibAST memory management system. First the pointers used to track - * allocated memory are dumped (that's what pointer #0 is); then, each - * allocated pointer is dumped along with its size and contents, the - * latter being displayed both in hexadecimal form and ASCII form. - * Non-printable characters are replaced by dots ('.'). You can see - * a sample of the output in the - * @link mem_example.c memory management system example @endlink. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink - * @ingroup DOXGRP_MEM - */ -/** * @def X_CREATE_PIXMAP(d, win, w, h, depth) * Create an X pixmap. * @@ -1194,119 +1082,79 @@ extern int re_exec(); * @see @link DOXGRP_MEM Memory Management Subsystem @endlink * @ingroup DOXGRP_MEM */ -/** - * @def MALLOC_CALL_INTERVAL - * MALLOC() call count interval. - * - * LibAST has the ability to count calls to MALLOC(); this defines the - * interval for reporting the call count. The default is 25, meaning - * that LibAST will print the current count every 25 calls. Note that - * MALLOC_CALL_COUNT must be defined when compiling LibAST, in - * addition to memory debugging, for this feature to work. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink - * @ingroup DOXGRP_MEM - */ -/** - * @def REALLOC_CALL_INTERVAL - * REALLOC() call count interval. - * - * LibAST has the ability to count calls to REALLOC(); this defines - * the interval for reporting the call count. The default is 25, - * meaning that LibAST will print the current count every 25 calls. - * Note that MALLOC_CALL_COUNT must be defined when compiling LibAST, - * in addition to memory debugging, for this feature to work. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink - * @ingroup DOXGRP_MEM - */ -/** - * @def CALLOC_CALL_INTERVAL - * CALLOC() call count interval. - * - * LibAST has the ability to count calls to CALLOC(); this defines the - * interval for reporting the call count. The default is 25, meaning - * that LibAST will print the current count every 25 calls. Note that - * MALLOC_CALL_COUNT must be defined when compiling LibAST, in - * addition to memory debugging, for this feature to work. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink - * @ingroup DOXGRP_MEM - */ -/** - * @def FREE_CALL_INTERVAL - * FREE() call count interval. - * - * LibAST has the ability to count calls to FREE(); this defines the - * interval for reporting the call count. The default is 25, meaning - * that LibAST will print the current count every 25 calls. Note that - * MALLOC_CALL_COUNT must be defined when compiling LibAST, in - * addition to memory debugging, for this feature to work. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink - * @ingroup DOXGRP_MEM - */ #if (DEBUG >= DEBUG_MEM) -# define MALLOC(sz) spifmem_malloc(__FILE__, __LINE__, (sz)) -# define CALLOC(type,n) spifmem_calloc(__FILE__, __LINE__, (n), (sizeof(type))) -# define REALLOC(mem,sz) spifmem_realloc(#mem, __FILE__, __LINE__, (mem), (sz)) -# define FREE(ptr) do { spifmem_free(#ptr, __FILE__, __LINE__, (ptr)); (ptr) = NULL; } while (0) # ifdef LIBAST_SUPPORT_MACRO_CSE -# define ALLOCA(sz) ({ void *p = alloca(sz); p; }) -# else -# define ALLOCA(sz) alloca(sz) -# endif -# define STRDUP(s) spifmem_strdup(#s, __FILE__, __LINE__, (s)) -# define MALLOC_DUMP() spifmem_dump_mem_tables() /* X11 Wrappers */ -# if 0 && defined(LIBAST_SUPPORT_MACRO_CSE) # define X_CREATE_PIXMAP(d, win, w, h, depth) ({ \ - Pixmap p = XCreatePixmap((d), (win), (w), (h), (depth)); \ - D_MEM(("Created %ux%u pixmap 0x%08x of depth %u for window 0x%08x at %s:%lu\n", (w), (h), p, (depth), (win), __FILE__, __LINE__)); \ - if (p == None) return p; \ - memrec_add_var(&pixmap_rec, (spif_charptr_t) NONULL(filename), line, (void *) p, w * h * (depth / 8)); \ - p; \ - }) -# endif -# define X_CREATE_PIXMAP(d, win, w, h, depth) spifmem_x_create_pixmap(__FILE__, __LINE__, (d), (win), (w), (h), (depth)) -# define X_FREE_PIXMAP(d, p) spifmem_x_free_pixmap(#p, __FILE__, __LINE__, (d), (p)) -# if LIBAST_IMLIB2_SUPPORT -# define IMLIB_REGISTER_PIXMAP(p) spifmem_imlib_register_pixmap(#p, __FILE__, __LINE__, (p)) -# define IMLIB_FREE_PIXMAP(p) spifmem_imlib_free_pixmap(#p, __FILE__, __LINE__, (p)) -# else -# define IMLIB_REGISTER_PIXMAP(p) NOP -# define IMLIB_FREE_PIXMAP(p) NOP -# endif -# define PIXMAP_DUMP() spifmem_dump_pixmap_tables() -# define X_CREATE_GC(d, win, f, gcv) spifmem_x_create_gc(__FILE__, __LINE__, (d), (win), (f), (gcv)) -# define X_FREE_GC(d, gc) spifmem_x_free_gc(#gc, __FILE__, __LINE__, (d), (gc)) -# define GC_DUMP() spifmem_dump_gc_tables() -# define MALLOC_CALL_INTERVAL 25 -# define REALLOC_CALL_INTERVAL 25 -# define CALLOC_CALL_INTERVAL 25 -# define FREE_CALL_INTERVAL 25 + Pixmap p = XCreatePixmap((d), (win), (w), (h), (depth)); \ + D_MEM(("Created %ux%u pixmap 0x%08x of depth %u for window 0x%08x at %s:%lu\n", \ + (w), (h), p, (depth), (win), __FILE__, __LINE__)); \ + if (p && (DEBUG_LEVEL >= DEBUG_MEM)) spifmem_add_var(__FILE__, __LINE__, (void *) p, w * h * (depth / 8), "X Pixmap"); \ + p; \ + }) +# define X_FREE_PIXMAP(d, p) do { \ + D_MEM(("Freeing pixmap %s (0x%08x) at %s:%lu\n", #p, p, __FILE__, __LINE__)); \ + if (p) { \ + if (DEBUG_LEVEL >= DEBUG_MEM) spifmem_rem_var(#p, __FILE__, __LINE__, (p)); \ + XFreePixmap((d), (p)); \ + } else { \ + D_MEM(("ERROR: Caught attempt to free NULL pixmap\n")); \ + } \ + } while (0) +# define X_CREATE_GC(d, win, f, gcv) ({ \ + GC gc = XCreateGC((d), (win), (mask), (gcv)); \ + D_MEM(("Created gc 0x%08x for window 0x%08x at %s:%lu\n", (int) gc, (win), __FILE__, __LINE__)); \ + if (gc && (DEBUG_LEVEL >= DEBUG_MEM)) spifmem_add_var(__FILE__, __LINE__, (void *) gc, sizeof(XGCValues), "X GC"); \ + gc; \ + }) +# define X_FREE_GC(d, gc) do { \ + D_MEM(("Freeing GC %s (0x%08x) at %s:%lu\n", #gc, gc, __FILE__, __LINE__)); \ + if (gc) { \ + if (DEBUG_LEVEL >= DEBUG_MEM) spifmem_rem_var(#gc, __FILE__, __LINE__, (gc)); \ + XFreeGC((d), (gc)); \ + } else { \ + D_MEM(("ERROR: Caught attempt to free NULL GC\n")); \ + } \ + } while (0) +# else /* LIBAST_SUPPORT_MACRO_CSE */ +# define X_CREATE_PIXMAP(d, win, w, h, depth) XCreatePixmap((d), (win), (w), (h), (depth)) +# define X_FREE_PIXMAP(d, p) XFreePixmap((d), (p)) +# define X_CREATE_GC(d, win, f, gcv) XCreateGC((d), (win), (f), (gcv)) +# define X_FREE_GC(d, gc) XFreeGC((d), (gc)) +# endif /* LIBAST_SUPPORT_MACRO_CSE */ +# define IMLIB_REGISTER_PIXMAP(p) do { \ + D_MEM(("Registering pixmap %s (0x%08x) created by Imlib2 at %s:%lu\n", #p, p, __FILE__, __LINE__)); \ + if (p) { \ + if (DEBUG_LEVEL >= DEBUG_MEM) { \ + if (!spifmem_find_var((void *) p)) { \ + spifmem_add_var(__FILE__, __LINE__, (void *) p, 1, "Imlib2 Pixmap"); \ + } else { \ + D_MEM(("Pixmap 0x%08x already registered.\n", p)); \ + } \ + } \ + } else { \ + D_MEM(("ERROR: Refusing to register a NULL pixmap\n")); \ + } \ + } while (0) +# define IMLIB_FREE_PIXMAP(p) do { \ + D_MEM(("Freeing pixmap %s (0x%08x) at %s:%lu using Imlib2\n", #p, p, __FILE__, __LINE__)); \ + if (p) { \ + if (DEBUG_LEVEL >= DEBUG_MEM) spifmem_rem_var(#p, __FILE__, __LINE__, (p)); \ + imlib_free_pixmap_and_mask(p); \ + } else { \ + D_MEM(("ERROR: Caught attempt to free NULL pixmap\n")); \ + } \ + } while (0) +# define SPIFMEM_DUMP() spifmem_dump_resources() #else -# define MALLOC(sz) malloc(sz) -# define CALLOC(type,n) calloc((n),(sizeof(type))) -# define REALLOC(mem,sz) ((sz) ? ((mem) ? (realloc((mem), (sz))) : (malloc(sz))) : ((mem) ? (free(mem), NULL) : (NULL))) -# define FREE(ptr) do { free(ptr); (ptr) = NULL; } while (0) -# define ALLOCA(sz) alloca(sz) -# define STRDUP(s) strdup((char *) s) -# define MALLOC_DUMP() NOP # define X_CREATE_PIXMAP(d, win, w, h, depth) XCreatePixmap((d), (win), (w), (h), (depth)) # define X_FREE_PIXMAP(d, p) XFreePixmap((d), (p)) -# ifdef LIBAST_IMLIB2_SUPPORT -# define IMLIB_REGISTER_PIXMAP(p) NOP -# define IMLIB_FREE_PIXMAP(p) imlib_free_pixmap_and_mask(p) -# else -# define IMLIB_REGISTER_PIXMAP(p) NOP -# define IMLIB_FREE_PIXMAP(p) NOP -# endif -# define PIXMAP_DUMP() NOP # define X_CREATE_GC(d, win, f, gcv) XCreateGC((d), (win), (f), (gcv)) # define X_FREE_GC(d, gc) XFreeGC((d), (gc)) -# define GC_DUMP() NOP +# define IMLIB_REGISTER_PIXMAP(p) NOP +# define IMLIB_FREE_PIXMAP(p) imlib_free_pixmap_and_mask(p) +# define SPIFMEM_DUMP() NOP #endif /** @@ -1329,7 +1177,6 @@ extern int re_exec(); * track of what pointers have been allocated, where they were * allocated, and how much space was requested. * - * @see MALLOC(), REALLOC(), CALLOC(), FREE() * @ingroup DOXGRP_MEM */ typedef struct spifmem_ptr_t { @@ -1337,6 +1184,8 @@ typedef struct spifmem_ptr_t { void *ptr; /** The pointer's size, in bytes. The pointer's size, in bytes. */ size_t size; + /** The resource type. The resource type. */ + char *type; /** Filename. The file which last (re)allocated the pointer. */ spif_char_t file[SPIFMEM_FNAME_LEN + 1]; /** Line number. The line number where the pointer was last (re)allocated. */ @@ -2837,30 +2686,11 @@ extern unsigned int DEBUG_LEVEL; /* mem.c */ extern void spifmem_init(void); -extern void memrec_add_var(spifmem_memrec_t *, const char *, unsigned long, void *, size_t); -extern spifmem_ptr_t *memrec_find_var(spifmem_memrec_t *, const void *); -extern void memrec_rem_var(spifmem_memrec_t *, const char *, const char *, unsigned long, const void *); -extern void memrec_chg_var(spifmem_memrec_t *, const char *, const char *, unsigned long, const void *, void *, size_t); -extern void memrec_dump_pointers(spifmem_memrec_t *); -extern void memrec_dump_resources(spifmem_memrec_t *); -extern void *spifmem_malloc(const char *, unsigned long, size_t); -extern void *spifmem_realloc(const char *, const char *, unsigned long, void *, size_t); -extern void *spifmem_calloc(const char *, unsigned long, size_t, size_t); -extern void spifmem_free(const char *, const char *, unsigned long, void *); -extern char *spifmem_strdup(const char *, const char *, unsigned long, const char *); -extern void spifmem_dump_mem_tables(void); -#if LIBAST_X11_SUPPORT -extern Pixmap spifmem_x_create_pixmap(const char *, unsigned long, Display *, Drawable, unsigned int, unsigned int, unsigned int); -extern void spifmem_x_free_pixmap(const char *, const char *, unsigned long, Display *, Pixmap); -# if LIBAST_IMLIB2_SUPPORT -extern void spifmem_imlib_register_pixmap(const char * var, const char * filename, unsigned long line, Pixmap p); -extern void spifmem_imlib_free_pixmap(const char * var, const char * filename, unsigned long line, Pixmap p); -# endif -extern void spifmem_dump_pixmap_tables(void); -extern GC spifmem_x_create_gc(const char *, unsigned long, Display *, Drawable, unsigned long, XGCValues *); -extern void spifmem_x_free_gc(const char *, const char *, unsigned long, Display *, GC); -extern void spifmem_dump_gc_tables(void); -#endif +extern void spifmem_add_var(const char *, unsigned long, void *, size_t, char *); +extern spifmem_ptr_t *spifmem_find_var(const void *); +extern void spifmem_rem_var(const char *, const char *, unsigned long, const void *); +extern void spifmem_chg_var(const char *, const char *, unsigned long, const void *, void *, size_t); +extern void spifmem_dump_resources(void); extern void spiftool_free_array(void *, size_t); /* file.c */ @@ -3016,4 +2846,15 @@ static void (*fatal_error)(const char *, ...) = libast_fatal_error; #endif /* LIBAST_COMPAT_05_API */ +#if LIBAST_COMPAT_07_API +# define MALLOC(sz) malloc(sz) +# define CALLOC(type,n) calloc((n),(sizeof(type))) +# define REALLOC(mem,sz) ((sz) ? ((mem) ? (realloc((mem), (sz))) : (malloc(sz))) : ((mem) ? (free(mem), NULL) : (NULL))) +# define FREE(ptr) do { free(ptr); (ptr) = NULL; } while (0) +# define STRDUP(s) strdup((char *) s) +# define MALLOC_DUMP() NOP +# define PIXMAP_DUMP() SPIFMEM_DUMP() +# define GC_DUMP() SPIFMEM_DUMP() +#endif /* LIBAST_COMPAT_07_API */ + #endif /* _LIBAST_H_ */ diff --git a/include/libast/sysdefs.h.in b/include/libast/sysdefs.h.in index 4344abd..320d7f3 100644 --- a/include/libast/sysdefs.h.in +++ b/include/libast/sysdefs.h.in @@ -96,6 +96,11 @@ # define LIBAST_COMPAT_05_API 0 #endif +/* App-definable; requests 0.7 API compatibility. */ +#ifndef LIBAST_COMPAT_07_API +# define LIBAST_COMPAT_07_API 0 +#endif + /* A bunch of security checks. */ #ifndef HAVE_RLIMIT_MEMLOCK # define HAVE_RLIMIT_MEMLOCK 0 @@ -179,74 +179,14 @@ dnl# dnl# LibAST macro for X11 support dnl# AC_DEFUN([AST_X11_SUPPORT], [ - AC_PATH_XTRA - if test ! -z "$X_CFLAGS"; then - if test -z "$CPPFLAGS"; then - CPPFLAGS="$X_CFLAGS" - else - CPPFLAGS="$CPPFLAGS $X_CFLAGS" - fi - fi - if test ! -z "$X_LIBS"; then - if test -z "$LDFLAGS"; then - LDFLAGS="$X_LIBS" - else - LDFLAGS="$LDFLAGS $X_LIBS" - fi - fi - LIBAST_X11_SUPPORT="" - if test "x$no_x" != "xyes"; then - AC_CHECK_LIB(X11, XOpenDisplay, [ - LIBAST_X11_SUPPORT="X11" - GRLIBS="-lX11" - AC_DEFINE([LIBAST_X11_SUPPORT], [1], [Define for X11 support.]) - ]) - fi - AC_SUBST(LIBAST_X11_SUPPORT) + : ]) dnl# dnl# LibAST macro for Imlib2 support dnl# AC_DEFUN([AST_IMLIB2_SUPPORT], [ - AC_ARG_WITH(imlib, - [ --with-imlib[=DIR] compile with Imlib2 support (default)], - [ - if test "$withval" != "no"; then - if test "$withval" != "yes"; then - CPPFLAGS="$CPPFLAGS -I${withval}/include" - LDFLAGS="$LDFLAGS -L${withval}/lib" - fi - USE_IMLIB=1 - else - USE_IMLIB=0 - fi - ], [ - USE_IMLIB=1 - ]) - LIBAST_IMLIB2_SUPPORT="" - if test $USE_IMLIB -eq 1 ; then - AC_CHECK_PROG(IMLIB2_CONFIG, imlib2-config, imlib2-config) - if test "x$IMLIB2_CONFIG" != "x"; then - GRLIBS="`$IMLIB2_CONFIG --libs`" - CFLAGS="$CFLAGS `$IMLIB2_CONFIG --cflags`" - AC_DEFINE([LIBAST_IMLIB2_SUPPORT], [1], [Define for Imlib2 support.]) - LIBAST_IMLIB2_SUPPORT="Imlib2" - else - AC_CHECK_LIB(m, pow, LIBS="-lm $LIBS") - AC_CHECK_LIB(dl, dlopen, LIBS="-ldl $LIBS") - AC_CHECK_LIB(freetype, FT_Init_FreeType, GRLIBS="-lfreetype $GRLIBS", , $GRLIBS) - AC_CHECK_LIB(Imlib2, imlib_create_image, [ - GRLIBS="-lImlib2 $GRLIBS" - AC_DEFINE([LIBAST_IMLIB2_SUPPORT], [1], [Define for Imlib2 support.]) - LIBAST_IMLIB2_SUPPORT="Imlib2" - ], [ - AC_WARN(*** Imlib2 support has been disabled because Imlib2 ***) - AC_WARN(*** was not found or could not be linked. ***) - ], $GRLIBS) - fi - fi - AC_SUBST(LIBAST_IMLIB2_SUPPORT) + : ]) dnl# diff --git a/src/Makefile.am b/src/Makefile.am index c8ecfaf..5f61d33 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,5 +11,5 @@ dlinked_list.c file.c linked_list.c mbuff.c mem.c module.c msgs.c \ obj.c objpair.c options.c pthreads.c regexp.c socket.c str.c strings.c \ snprintf.c tok.c url.c ustr.c -libast_la_LDFLAGS = -version-info 2:2:0 +libast_la_LDFLAGS = -version-info 3:0:0 MAINTAINERCLEANFILES = Makefile.in @@ -36,62 +36,15 @@ #include "libast_internal.h" -#if MALLOC_CALL_COUNT -/*@{*/ /** - * @name Memory Management Call Tracking - * Count calls to memory management functions. + * Allocated resources. * - * This group of variables is used to count calls to the memory - * management functions. Call counting is controlled by the - * #MALLOC_CALL_COUNT symbol, and is off by default. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink - * @ingroup DOXGRP_MEM - */ - -/** Count calls to MALLOC(). Count calls to MALLOC(). */ -static int malloc_count = 0; -/** Count calls to CALLOC(). Count calls to CALLOC(). */ -static int calloc_count = 0; -/** Count calls to REALLOC(). Count calls to REALLOC(). */ -static int realloc_count = 0; -/** Count calls to FREE(). Count calls to FREE(). */ -static int free_count = 0; -/*@}*/ -#endif - -/** - * Allocated pointers. - * - * This structure keeps track of the pointer array which represents - * pointers allocated via the memory management interface. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, spifmem_memrec_t_struct - * @ingroup DOXGRP_MEM - */ -static spifmem_memrec_t malloc_rec; -/** - * Allocated pixmaps. - * - * This structure keeps track of the pixmap array which represents - * pixmaps allocated via the memory management interface. + * This structure keeps track of generic resources. * * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, spifmem_memrec_t_struct * @ingroup DOXGRP_MEM */ -static spifmem_memrec_t pixmap_rec; -/** - * Allocated GC's. - * - * This structure keeps track of the GC array which represents - * X11 Graphics Context objects, or GC's, allocated via the memory - * management interface. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, spifmem_memrec_t_struct - * @ingroup DOXGRP_MEM - */ -static spifmem_memrec_t gc_rec; +static spifmem_memrec_t resource_rec; /** * Initialize memory management system. @@ -107,55 +60,46 @@ void spifmem_init(void) { D_MEM(("Constructing memory allocation records\n")); - malloc_rec.ptrs = (spifmem_ptr_t *) malloc(sizeof(spifmem_ptr_t)); - pixmap_rec.ptrs = (spifmem_ptr_t *) malloc(sizeof(spifmem_ptr_t)); - gc_rec.ptrs = (spifmem_ptr_t *) malloc(sizeof(spifmem_ptr_t)); + resource_rec.ptrs = (spifmem_ptr_t *) malloc(sizeof(spifmem_ptr_t)); } /** - * Add a variable to a record set. + * Add a resource to be tracked. * - * This is the static, internal-use-only function that does the actual - * work of recording information on a variable to be tracked. This - * information includes file and line number information and is stored - * as a #spifmem_ptr_t. - * - * @param memrec Address of the #spifmem_memrec_t we're adding to. * @param filename The filename where the variable was allocated. * @param line The line number of @a filename where the variable * was allocated. * @param ptr The allocated variable. - * @param size The number of bytes requested. + * @param size The size of the resource in bytes. + * @param type The type of resource being tracked. * * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, MALLOC(), libast_malloc() * @ingroup DOXGRP_MEM */ void -memrec_add_var(spifmem_memrec_t *memrec, const char *filename, unsigned long line, void *ptr, size_t size) +spifmem_add_var(const char *filename, unsigned long line, void *ptr, size_t size, char *type) { register spifmem_ptr_t *p; - ASSERT(memrec != NULL); - memrec->cnt++; - if (!(memrec->ptrs = (spifmem_ptr_t *)realloc(memrec->ptrs, sizeof(spifmem_ptr_t) * memrec->cnt))) { + resource_rec.cnt++; + if (!(resource_rec.ptrs = (spifmem_ptr_t *)realloc(resource_rec.ptrs, sizeof(spifmem_ptr_t) * resource_rec.cnt))) { D_MEM(("Unable to reallocate pointer list -- %s\n", strerror(errno))); } - p = memrec->ptrs + memrec->cnt - 1; + p = resource_rec.ptrs + resource_rec.cnt - 1; D_MEM(("Adding variable (%10p, %lu bytes) from %s:%lu.\n", ptr, size, filename, line)); - D_MEM(("Storing as pointer #%lu at %10p (from %10p).\n", memrec->cnt, p, memrec->ptrs)); + D_MEM(("Storing as pointer #%lu at %10p (from %10p).\n", resource_rec.cnt, p, resource_rec.ptrs)); p->ptr = ptr; p->size = size; spiftool_safe_strncpy(p->file, (const spif_charptr_t) filename, sizeof(p->file)); p->line = line; + p->type = type; } /** - * Find a variable within a record set. + * Find a variable within the list of tracked resources. * - * This function searches through the pointer list of the specified - * @a memrec object for a given pointer. + * This function searches through the resource list for a given resource ID. * - * @param memrec Address of the #spifmem_memrec_t we're searching. * @param ptr The value of the requested pointer. * @return A pointer to the #spifmem_ptr_t object within @a memrec * that matches @a ptr, or NULL if not found. @@ -164,17 +108,16 @@ memrec_add_var(spifmem_memrec_t *memrec, const char *filename, unsigned long lin * @ingroup DOXGRP_MEM */ spifmem_ptr_t * -memrec_find_var(spifmem_memrec_t *memrec, const void *ptr) +spifmem_find_var(const void *ptr) { register spifmem_ptr_t *p; register unsigned long i; - ASSERT_RVAL(memrec != NULL, NULL); REQUIRE_RVAL(ptr != NULL, NULL); - for (i = 0, p = memrec->ptrs; i < memrec->cnt; i++, p++) { + for (i = 0, p = resource_rec.ptrs; i < resource_rec.cnt; i++, p++) { if (p->ptr == ptr) { - D_MEM(("Found pointer #%lu stored at %10p (from %10p)\n", i + 1, p, memrec->ptrs)); + D_MEM(("Found pointer #%lu stored at %10p (from %10p)\n", i + 1, p, resource_rec.ptrs)); return p; } } @@ -182,12 +125,8 @@ memrec_find_var(spifmem_memrec_t *memrec, const void *ptr) } /** - * Remove a variable from a record set. - * - * This is the static, internal-use-only function that does the actual - * work of freeing recorded information for a deleted pointer. + * Remove a variable from the list of tracked resources. * - * @param memrec Address of the #spifmem_memrec_t we're removing from. * @param var The variable name being freed (for diagnostic * purposes only). * @param filename The filename where the variable was freed. @@ -199,34 +138,29 @@ memrec_find_var(spifmem_memrec_t *memrec, const void *ptr) * @ingroup DOXGRP_MEM */ void -memrec_rem_var(spifmem_memrec_t *memrec, const char *var, const char *filename, unsigned long line, const void *ptr) +spifmem_rem_var(const char *var, const char *filename, unsigned long line, const void *ptr) { register spifmem_ptr_t *p; - ASSERT(memrec != NULL); USE_VAR(var); USE_VAR(filename); USE_VAR(line); - if (!(p = memrec_find_var(memrec, ptr))) { - D_MEM(("ERROR: File %s, line %d attempted to free variable %s (%10p) which was not allocated with MALLOC/REALLOC\n", + if (!(p = spifmem_find_var(ptr))) { + D_MEM(("ERROR: File %s, line %d attempted to free resource %s (%10p) which was not registered.\n", filename, line, var, ptr)); return; } D_MEM(("Removing variable %s (%10p) of size %lu\n", var, ptr, p->size)); - if ((--memrec->cnt) > 0) { - memmove(p, p + 1, sizeof(spifmem_ptr_t) * (memrec->cnt - (p - memrec->ptrs))); - memrec->ptrs = (spifmem_ptr_t *) realloc(memrec->ptrs, sizeof(spifmem_ptr_t) * memrec->cnt); + if ((--resource_rec.cnt) > 0) { + memmove(p, p + 1, sizeof(spifmem_ptr_t) * (resource_rec.cnt - (p - resource_rec.ptrs))); + resource_rec.ptrs = (spifmem_ptr_t *) realloc(resource_rec.ptrs, sizeof(spifmem_ptr_t) * resource_rec.cnt); } } /** - * Resize a variable in a record set. + * Resize a tracked resource. * - * This is the static, internal-use-only function that does the actual - * work of altering information on a tracked variable. - * - * @param memrec Address of the #spifmem_memrec_t we're modifying. * @param var The variable name being resized (for diagnostic * purposes only). * @param filename The filename where the variable was resized. @@ -240,143 +174,50 @@ memrec_rem_var(spifmem_memrec_t *memrec, const char *var, const char *filename, * @ingroup DOXGRP_MEM */ void -memrec_chg_var(spifmem_memrec_t *memrec, const char *var, const char *filename, unsigned long line, const void *oldp, void *newp, size_t size) +spifmem_chg_var(const char *var, const char *filename, unsigned long line, const void *oldp, void *newp, size_t size) { register spifmem_ptr_t *p; - ASSERT(memrec != NULL); USE_VAR(var); - if (!(p = memrec_find_var(memrec, oldp))) { - D_MEM(("ERROR: File %s, line %d attempted to realloc variable %s (%10p) which was not allocated with MALLOC/REALLOC\n", filename, + if (!(p = spifmem_find_var(oldp))) { + D_MEM(("ERROR: File %s, line %d attempted to realloc untracked resource %s (%10p).\n", filename, line, var, oldp)); return; } D_MEM(("Changing variable %s (%10p, %lu -> %10p, %lu)\n", var, oldp, p->size, newp, size)); p->ptr = newp; p->size = size; - spiftool_safe_strncpy(p->file, (const spif_charptr_t) filename, sizeof(p->file)); + spiftool_safe_strncpy(p->file, filename, sizeof(p->file)); p->line = line; } /** - * Dump listing of tracked pointers. - * - * This function dumps a listing of all pointers in @a memrec along - * with the filename, line number, address, size, and contents for - * each. Contents are displayed in both hex and ASCII, the latter - * having non-printable characters replaced with periods ('.'). - * - * @param memrec Address of the #spifmem_memrec_t we're dumping. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, MALLOC_DUMP(), libast_dump_mem_tables() - * @ingroup DOXGRP_MEM - */ -void -memrec_dump_pointers(spifmem_memrec_t *memrec) -{ - register spifmem_ptr_t *p; - unsigned long i, j, k, l, total = 0; - unsigned long len; - spif_char_t buff[9]; - - ASSERT(memrec != NULL); - fprintf(LIBAST_DEBUG_FD, "PTR: %lu pointers stored.\n", (unsigned long) memrec->cnt); - fprintf(LIBAST_DEBUG_FD, - "PTR: Pointer | Filename | Line | Address | Size | Offset | 00 01 02 03 04 05 06 07 | ASCII \n"); - fprintf(LIBAST_DEBUG_FD, - "PTR: ---------+----------------------+--------+----------+--------+---------+-------------------------+---------\n"); - fflush(LIBAST_DEBUG_FD); - len = sizeof(spifmem_ptr_t) * memrec->cnt; - memset(buff, 0, sizeof(buff)); - - /* First, dump the contents of the memrec->ptrs[] array. */ - for (p = memrec->ptrs, j = 0; j < len; j += 8) { - fprintf(LIBAST_DEBUG_FD, "PTR: %07lu | %20s | %6lu | %10p | %06lu | %07x | ", - (unsigned long) 0, "", (unsigned long) 0, - (spif_ptr_t) memrec->ptrs, - (unsigned long) (sizeof(spifmem_ptr_t) * memrec->cnt), (unsigned int) j); - /* l is the number of characters we're going to output */ - l = ((len - j < 8) ? (len - j) : (8)); - /* Copy l bytes (up to 8) from memrec->ptrs[] (p) to buffer */ - memcpy(buff, ((char *) p) + j, l); - buff[l] = 0; - for (k = 0; k < l; k++) { - fprintf(LIBAST_DEBUG_FD, "%02x ", buff[k]); - } - /* If we printed less than 8 bytes worth, pad with 3 spaces per byte */ - for (; k < 8; k++) { - fprintf(LIBAST_DEBUG_FD, " "); - } - /* Finally, print the printable ASCII string for those l bytes */ - fprintf(LIBAST_DEBUG_FD, "| %-8s\n", spiftool_safe_str((char *) buff, l)); - /* Flush after every line in case we crash */ - fflush(LIBAST_DEBUG_FD); - } - - /* Now print out each pointer and its contents. */ - for (i = 0; i < memrec->cnt; p++, i++) { - /* Add this pointer's size to our total */ - total += p->size; - for (j = 0; j < p->size; j += 8) { - fprintf(LIBAST_DEBUG_FD, "PTR: %07lu | %20s | %6lu | %10p | %06lu | %07x | ", - i + 1, NONULL(p->file), (unsigned long) p->line, - p->ptr, (unsigned long) p->size, (unsigned) j); - /* l is the number of characters we're going to output */ - l = ((p->size - j < 8) ? (p->size - j) : (8)); - /* Copy l bytes (up to 8) from p->ptr to buffer */ - memcpy(buff, ((char *) p->ptr) + j, l); - buff[l] = 0; - for (k = 0; k < l; k++) { - fprintf(LIBAST_DEBUG_FD, "%02x ", buff[k]); - } - /* If we printed less than 8 bytes worth, pad with 3 spaces per byte */ - for (; k < 8; k++) { - fprintf(LIBAST_DEBUG_FD, " "); - } - /* Finally, print the printable ASCII string for those l bytes */ - fprintf(LIBAST_DEBUG_FD, "| %-8s\n", spiftool_safe_str(buff, l)); - /* Flush after every line in case we crash */ - fflush(LIBAST_DEBUG_FD); - } - } - fprintf(LIBAST_DEBUG_FD, "PTR: Total allocated memory: %10lu bytes\n", total); - fflush(LIBAST_DEBUG_FD); -} - -/** * Dump listing of tracked resources. * - * This function is very similar to memrec_dump_pointers() but is - * intended for use with non-pointer data. - * - * @param memrec Address of the #spifmem_memrec_t we're dumping. - * * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, MALLOC_DUMP(), libast_dump_mem_tables(), - * memrec_dump_pointers() + * spifmem_dump_pointers() * @ingroup DOXGRP_MEM */ void -memrec_dump_resources(spifmem_memrec_t *memrec) +spifmem_dump_resources(void) { register spifmem_ptr_t *p; unsigned long i, total; unsigned long len; - ASSERT(memrec != NULL); - len = memrec->cnt; + len = resource_rec.cnt; fprintf(LIBAST_DEBUG_FD, "RES: %lu resources stored.\n", - (unsigned long) memrec->cnt); - fprintf(LIBAST_DEBUG_FD, "RES: Index | Resource ID | Filename | Line | Size \n"); - fprintf(LIBAST_DEBUG_FD, "RES: -------+-------------+----------------------+--------+--------\n"); + (unsigned long) resource_rec.cnt); + fprintf(LIBAST_DEBUG_FD, "RES: Index | Resource ID | Filename | Line | Size | Type\n"); + fprintf(LIBAST_DEBUG_FD, "RES: -------+-------------+----------------------+--------+--------+----------\n"); fflush(LIBAST_DEBUG_FD); - for (p = memrec->ptrs, i = 0, total = 0; i < len; i++, p++) { + for (p = resource_rec.ptrs, i = 0, total = 0; i < len; i++, p++) { total += p->size; - fprintf(LIBAST_DEBUG_FD, "RES: %5lu | 0x%08lx | %20s | %6lu | %6lu\n", - i, (unsigned long) p->ptr, NONULL(p->file), - (unsigned long) p->line, - (unsigned long) p->size); + fprintf(LIBAST_DEBUG_FD, "RES: %5lu | 0x%08lx | %20s | %6lu | %6lu | %-8s\n", + i, (unsigned long) p->ptr, NONULL(p->file), (unsigned long) p->line, + (unsigned long) p->size, p->type); /* Flush after every line in case we crash */ fflush(LIBAST_DEBUG_FD); } @@ -384,468 +225,6 @@ memrec_dump_resources(spifmem_memrec_t *memrec) fflush(LIBAST_DEBUG_FD); } -/******************** MEMORY ALLOCATION INTERFACE ********************/ - -/** - * LibAST implementation of malloc(). - * - * When memory debugging is active (via #DEBUG_MEM), all calls to the - * MALLOC() macro are routed here. The macro allows filename and line - * number information to be provided thanks to the __FILE__ and - * __LINE__ symbols pre-defined by cpp. - * - * @param filename The filename where the variable is being - * allocated. - * @param line The line number of @a filename where the variable - * is being allocated. - * @param size The requested size in bytes (as passed to MALLOC()). - * @return A pointer to the newly-allocated memory. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, MALLOC() - * @ingroup DOXGRP_MEM - */ -void * -spifmem_malloc(const char *filename, unsigned long line, size_t size) -{ - void *temp; - -#if MALLOC_CALL_COUNT - ++malloc_count; - if (!(malloc_count % MALLOC_CALL_INTERVAL)) { - fprintf(LIBAST_DEBUG_FD, "Calls to malloc(): %d\n", malloc_count); - } -#endif - - D_MEM(("%lu bytes requested at %s:%lu\n", size, NONULL(filename), line)); - - temp = (void *) malloc(size); - ASSERT_RVAL(!SPIF_PTR_ISNULL(temp), (spif_ptr_t) NULL); - if (DEBUG_LEVEL >= DEBUG_MEM) { - memrec_add_var(&malloc_rec, NONULL(filename), line, temp, size); - } - return (temp); -} - -/** - * LibAST implementation of realloc(). - * - * When memory debugging is active (via #DEBUG_MEM), all calls to the - * REALLOC() macro are routed here. The macro allows variable name, - * filename, and line number information to be provided. - * - * @param var The variable name being resized. - * @param filename The filename where the variable is being - * reallocated. - * @param line The line number of @a filename where the variable - * is being reallocated. - * @param ptr The old value of the pointer being resized. - * @param size The new requested size in bytes (as passed to - * REALLOC()). - * @return The new value (possibly moved) of the pointer. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, REALLOC() - * @ingroup DOXGRP_MEM - */ -void * -spifmem_realloc(const char *var, const char *filename, unsigned long line, void *ptr, size_t size) -{ - void *temp; - -#if MALLOC_CALL_COUNT - ++realloc_count; - if (!(realloc_count % REALLOC_CALL_INTERVAL)) { - D_MEM(("Calls to realloc(): %d\n", realloc_count)); - } -#endif - - D_MEM(("Variable %s (%10p -> %lu) at %s:%lu\n", var, ptr, (unsigned long) size, NONULL(filename), line)); - if (!ptr) { - temp = (void *) spifmem_malloc(filename, line, size); - } else if (size == 0) { - spifmem_free(var, filename, line, ptr); - temp = NULL; - } else { - temp = (void *) realloc(ptr, size); - ASSERT_RVAL(!SPIF_PTR_ISNULL(temp), (spif_ptr_t) NULL); - if (DEBUG_LEVEL >= DEBUG_MEM) { - memrec_chg_var(&malloc_rec, var, NONULL(filename), line, ptr, temp, size); - } - } - return (temp); -} - -/** - * LibAST implementation of calloc(). - * - * When memory debugging is active (via #DEBUG_MEM), all calls to the - * CALLOC() macro are routed here. The macro allows filename and line - * number information to be provided thanks to the __FILE__ and - * __LINE__ symbols pre-defined by cpp. - * - * @param filename The filename where the variable is being - * allocated. - * @param line The line number of @a filename where the variable - * is being allocated. - * @param count The number of objects being allocated. - * @param size The size in bytes of each object (as passed to - * CALLOC()). - * @return A pointer to the newly-allocated, zeroed memory. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, CALLOC() - * @ingroup DOXGRP_MEM - */ -void * -spifmem_calloc(const char *filename, unsigned long line, size_t count, size_t size) -{ - void *temp; - size_t total_size; - - total_size = size * count; -#if MALLOC_CALL_COUNT - ++calloc_count; - if (!(calloc_count % CALLOC_CALL_INTERVAL)) { - fprintf(LIBAST_DEBUG_FD, "Calls to calloc(): %d\n", calloc_count); - } -#endif - - D_MEM(("%lu units of %lu bytes each (%lu bytes total) requested at %s:%lu\n", - count, size, total_size, NONULL(filename), line)); - temp = (void *) calloc(count, size); - ASSERT_RVAL(!SPIF_PTR_ISNULL(temp), (spif_ptr_t) NULL); - if (DEBUG_LEVEL >= DEBUG_MEM) { - memrec_add_var(&malloc_rec, NONULL(filename), line, temp, total_size); - } - return (temp); -} - -/** - * LibAST implementation of free(). - * - * When memory debugging is active (via #DEBUG_MEM), all calls to the - * FREE() macro are routed here. The macro allows variable name, - * filename, and line number information to be provided. - * - * @param var The variable name being freed. - * @param filename The filename where the variable is being freed. - * @param line The line number of @a filename where the variable - * is being freed. - * @param ptr The pointer being freed (as passed to FREE()). - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, FREE() - * @ingroup DOXGRP_MEM - */ -void -spifmem_free(const char *var, const char *filename, unsigned long line, void *ptr) -{ -#if MALLOC_CALL_COUNT - ++free_count; - if (!(free_count % FREE_CALL_INTERVAL)) { - fprintf(LIBAST_DEBUG_FD, "Calls to free(): %d\n", free_count); - } -#endif - - D_MEM(("Variable %s (%10p) at %s:%lu\n", var, ptr, NONULL(filename), line)); - if (ptr) { - if (DEBUG_LEVEL >= DEBUG_MEM) { - memrec_rem_var(&malloc_rec, var, NONULL(filename), line, ptr); - } - free(ptr); - } else { - D_MEM(("ERROR: Caught attempt to free NULL pointer\n")); - } -} - -/** - * LibAST implementation of strdup(). - * - * When memory debugging is active (via #DEBUG_MEM), all calls to the - * STRDUP() macro are routed here. The macro allows variable name, - * filename, and line number information to be provided. - * - * @param var The variable name being duplicated. - * @param filename The filename where the variable is being duplicated. - * @param line The line number of @a filename where the variable - * is being duplicated. - * @param str The string being duplicated (as passed to STRDUP()). - * @return A pointer to a newly-allocated copy of @a str. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, STRDUP() - * @ingroup DOXGRP_MEM - */ -char * -spifmem_strdup(const char *var, const char *filename, unsigned long line, const char *str) -{ - register char *newstr; - register size_t len; - - ASSERT_RVAL(!SPIF_PTR_ISNULL(str), (char *) NULL); - USE_VAR(var); - D_MEM(("Variable %s (%10p) at %s:%lu\n", var, str, NONULL(filename), line)); - - len = strlen((char *) str) + 1; /* Copy NUL byte also */ - newstr = (char *) spifmem_malloc(NONULL(filename), line, len); - ASSERT_RVAL(!SPIF_PTR_ISNULL(newstr), (spif_ptr_t) NULL); - strcpy((char *) newstr, (char *) str); - return (newstr); -} - -/** - * Dump listing of tracked pointers. - * - * This function simply calls memrec_dump_pointers() and passes in the - * address of the #malloc_rec variable. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, MALLOC_DUMP(), memrec_dump_pointers() - * @ingroup DOXGRP_MEM - */ -void -spifmem_dump_mem_tables(void) -{ - fprintf(LIBAST_DEBUG_FD, "Dumping memory allocation table:\n"); - memrec_dump_pointers(&malloc_rec); -} - -#if LIBAST_X11_SUPPORT - -/******************** PIXMAP ALLOCATION INTERFACE ********************/ - -/** - * LibAST implementation of XCreatePixmap(). - * - * When memory debugging is active (via #DEBUG_MEM), all calls to the - * X_CREATE_PIXMAP() macro are routed here. The macro allows filename - * and line number information to be provided thanks to the __FILE__ - * and __LINE__ symbols pre-defined by cpp. - * - * @param filename The filename where the pixmap is being created. - * @param line The line number of @a filename where the pixmap is - * being created. - * @param d The Display for the new pixmap. - * @param win The Drawable for the new pixmap. - * @param w Width of the pixmap, in pixels. - * @param h Height of the pixmap, in pixels. - * @param depth The color depth for the new pixmap. - * @return A newly-created Pixmap. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, X_CREATE_PIXMAP() - * @ingroup DOXGRP_MEM - */ -Pixmap -spifmem_x_create_pixmap(const char *filename, unsigned long line, Display * d, Drawable win, unsigned int w, unsigned int h, - unsigned int depth) -{ - Pixmap p; - - p = XCreatePixmap(d, win, w, h, depth); - D_MEM(("Created %ux%u pixmap 0x%08x of depth %u for window 0x%08x at %s:%lu\n", w, h, p, depth, win, NONULL(filename), line)); - ASSERT_RVAL(p != None, None); - if (DEBUG_LEVEL >= DEBUG_MEM) { - memrec_add_var(&pixmap_rec, NONULL(filename), line, (void *) p, w * h * (depth / 8)); - } - return (p); -} - -/** - * LibAST implementation of XFreePixmap(). - * - * When memory debugging is active (via #DEBUG_MEM), all calls to the - * X_FREE_PIXMAP() macro are routed here. The macro allows variable - * name, filename, and line number information to be provided. - * - * @param var The variable name of the pixmap being freed. - * @param filename The filename where the pixmap is being freed. - * @param line The line number of @a filename where the pixmap is - * being freed. - * @param d The Display for the pixmap. - * @param p The Pixmap to be freed. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, X_FREE_PIXMAP() - * @ingroup DOXGRP_MEM - */ -void -spifmem_x_free_pixmap(const char *var, const char *filename, unsigned long line, Display * d, Pixmap p) -{ - D_MEM(("Freeing pixmap %s (0x%08x) at %s:%lu\n", var, p, NONULL(filename), line)); - if (p) { - if (DEBUG_LEVEL >= DEBUG_MEM) { - memrec_rem_var(&pixmap_rec, var, NONULL(filename), line, (void *) p); - } - XFreePixmap(d, p); - } else { - D_MEM(("ERROR: Caught attempt to free NULL pixmap\n")); - } -} - -# if LIBAST_IMLIB2_SUPPORT -/** - * Register a pixmap for tracking. - * - * Imlib has its own mechanism for creating pixmaps internally. In - * order to keep track of these pixmaps, they must be registered with - * LibAST using this function (via the IMLIB_REGISTER_PIXMAP() macro). - * - * @param var The variable name of the pixmap being registered. - * @param filename The filename where the pixmap is being registered. - * @param line The line number of @a filename where the pixmap is - * being registered. - * @param p The Pixmap being registered. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, IMLIB_REGISTER_PIXMAP() - * @ingroup DOXGRP_MEM - */ -void -spifmem_imlib_register_pixmap(const char *var, const char *filename, unsigned long line, Pixmap p) -{ - USE_VAR(var); - D_MEM(("Registering pixmap %s (0x%08x) created by Imlib2 at %s:%lu\n", var, p, NONULL(filename), line)); - if (p) { - if (DEBUG_LEVEL >= DEBUG_MEM) { - if (!memrec_find_var(&pixmap_rec, (void *) p)) { - memrec_add_var(&pixmap_rec, NONULL(filename), line, (void *) p, 1); - } else { - D_MEM(("Pixmap 0x%08x already registered.\n")); - } - } - } else { - D_MEM(("ERROR: Refusing to register a NULL pixmap\n")); - } -} - -/** - * Free a pixmap created by Imlib. - * - * Imlib has its own mechanism for freeing pixmaps, and their - * associated mask (if any), internally. All pixmaps created by Imlib - * must also be freed by Imlib. It is safe, albeit a bit slower, to - * free all pixmaps via Imlib, regardless of how they were created. - * - * @param var The variable name of the pixmap being freed. - * @param filename The filename where the pixmap is being freed. - * @param line The line number of @a filename where the pixmap is - * being freed. - * @param p The Pixmap being freed. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, IMLIB_FREE_PIXMAP() - * @ingroup DOXGRP_MEM - */ -void -spifmem_imlib_free_pixmap(const char *var, const char *filename, unsigned long line, Pixmap p) -{ - D_MEM(("Freeing pixmap %s (0x%08x) at %s:%lu using Imlib2\n", var, p, NONULL(filename), line)); - if (p) { - if (DEBUG_LEVEL >= DEBUG_MEM) { - memrec_rem_var(&pixmap_rec, var, NONULL(filename), line, (void *) p); - } - imlib_free_pixmap_and_mask(p); - } else { - D_MEM(("ERROR: Caught attempt to free NULL pixmap\n")); - } -} -# endif - -/** - * Dump listing of tracked pixmaps. - * - * This function simply calls memrec_dump_resources() and passes in - * the address of the #pixmap_rec variable. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, PIXMAP_DUMP(), memrec_dump_resources() - * @ingroup DOXGRP_MEM - */ -void -spifmem_dump_pixmap_tables(void) -{ - fprintf(LIBAST_DEBUG_FD, "Dumping X11 Pixmap allocation table:\n"); - memrec_dump_resources(&pixmap_rec); -} - - - -/********************** GC ALLOCATION INTERFACE **********************/ - -/** - * LibAST implementation of XCreateGC(). - * - * When memory debugging is active (via #DEBUG_MEM), all calls to the - * X_CREATE_GC() macro are routed here. The macro allows filename - * and line number information to be provided thanks to the __FILE__ - * and __LINE__ symbols pre-defined by cpp. - * - * @param filename The filename where the GC is being created. - * @param line The line number of @a filename where the GC is - * being created. - * @param d The Display for the new GC. - * @param win The Drawable for the new GC. - * @param mask Bitwise OR of zero or more GC flags. - * @param gcv Pointer to XGCValues structure. - * @return A newly-created GC. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, X_CREATE_GC() - * @ingroup DOXGRP_MEM - */ -GC -spifmem_x_create_gc(const char *filename, unsigned long line, Display * d, Drawable win, unsigned long mask, XGCValues * gcv) -{ - GC gc; - - D_MEM(("Creating gc for window 0x%08x at %s:%lu\n", win, NONULL(filename), line)); - - gc = XCreateGC(d, win, mask, gcv); - ASSERT_RVAL(gc != None, None); - if (DEBUG_LEVEL >= DEBUG_MEM) { - memrec_add_var(&gc_rec, NONULL(filename), line, (void *) gc, sizeof(XGCValues)); - } - return (gc); -} - -/** - * LibAST implementation of XFreeGC(). - * - * When memory debugging is active (via #DEBUG_MEM), all calls to the - * X_FREE_GC() macro are routed here. The macro allows variable - * name, filename, and line number information to be provided. - * - * @param var The variable name of the GC being freed. - * @param filename The filename where the GC is being freed. - * @param line The line number of @a filename where the GC is - * being freed. - * @param d The Display for the GC. - * @param gc The GC to be freed. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, X_FREE_GC() - * @ingroup DOXGRP_MEM - */ -void -spifmem_x_free_gc(const char *var, const char *filename, unsigned long line, Display * d, GC gc) -{ - D_MEM(("spifmem_x_free_gc() called for variable %s (0x%08x) at %s:%lu\n", var, gc, NONULL(filename), line)); - if (gc) { - if (DEBUG_LEVEL >= DEBUG_MEM) { - memrec_rem_var(&gc_rec, var, NONULL(filename), line, (void *) gc); - } - XFreeGC(d, gc); - } else { - D_MEM(("ERROR: Caught attempt to free NULL GC\n")); - } -} - -/** - * Dump listing of tracked GC's. - * - * This function simply calls memrec_dump_resources() and passes in - * the address of the #gc_rec variable. - * - * @see @link DOXGRP_MEM Memory Management Subsystem @endlink, GC_DUMP(), memrec_dump_resources() - * @ingroup DOXGRP_MEM - */ -void -spifmem_dump_gc_tables(void) -{ - fprintf(LIBAST_DEBUG_FD, "Dumping X11 GC allocation table:\n"); - memrec_dump_resources(&gc_rec); -} -#endif - /** * Free an array of pointers. * @@ -886,27 +265,34 @@ spiftool_free_array(void *list, size_t count) * This group of functions/defines/macros implements the memory * management subsystem within LibAST. * - * LibAST provides a robust mechanism for tracking memory allocations - * and deallocations. This system employs macro-based wrappers - * around the standard libc malloc/realloc/calloc/free routines, other - * libc fare such as strdup(), Xlib GC and Pixmap create/free - * routines, and even Imlib2's own pixmap functions. + * LibAST provides a mechanism for tracking resource allocations and + * deallocations. This system employs macro-based wrappers around + * various resource allocators/deallocators such as Xlib GC and Pixmap + * create/free routines and Imlib2 pixmap functions. * * To take advantage of this system, simply substitute the macro * versions in place of the standard versions throughout your code - * (e.g., use MALLOC() instead of malloc(), X_FREE_GC() instead of - * XFreeGC(), etc.). If DEBUG is set to a value higher than - * DEBUG_MEM, the LibAST-custom versions of these functions will be - * used. Of course, if memory debugging has not been requested, the - * original libc/XLib/Imlib2 versions will be used instead, so that - * you only incur the debugging overhead when you want it. - * - * LibAST has also been designed to work effectively with Gray - * Watson's excellent malloc-debugging library, dmalloc - * (http://dmalloc.com/), either instead of or in addition to its own - * memory tracking routines. Unlike LibAST, dmalloc supplements - * memory allocation tracking with fence-post checking, freed pointer - * reuse detection, and other very handy features. + * (e.g., X_FREE_GC() instead of XFreeGC()). If DEBUG is set to a + * value higher than DEBUG_MEM, the LibAST-custom versions of these + * functions will be used. Of course, if memory debugging has not + * been requested, the original libc/XLib/Imlib2 versions will be used + * instead, so that you only incur the debugging overhead when you + * want it. + * + * You can also define your own macros to wrap allocators and + * deallocators if LibAST doesn't already contain support for the + * resources you wish to track. Simply call spifmem_add_var(), + * spifmem_chg_var(), and spifmem_rem_var() whenever the resource is + * created, resized, or deleted (respectively). + * + * NOTE: If your compiler does not support compound statement + * expressions (i.e., a code block whose final statement specifies the + * value of a parenthesized expression, such as: + * ({int a = 1, b = 2; a *= b; b += a; a+b;})), + * LibAST's built-in wrapper macros will not be available to you, nor + * are you likely to be able to wrap many allocator functions with + * your own macros. In these situations, you'll need to call the + * LibAST memory routines separately. * * A small sample program demonstrating use of LibAST's memory * management system can be found @@ -927,20 +313,20 @@ spiftool_free_array(void *list, size_t count) * @code * $ ./mem_example * [1045859036] mem.c | 246: spifmem_malloc(): 500 bytes requested at mem_example.c:27 - * [1045859036] mem.c | 74: memrec_add_var(): Adding variable (0x8049a20, 500 bytes) from mem_example.c:27. - * [1045859036] mem.c | 75: memrec_add_var(): Storing as pointer #1 at 0x8049c18 (from 0x8049c18). + * [1045859036] mem.c | 74: spifmem_add_var(): Adding variable (0x8049a20, 500 bytes) from mem_example.c:27. + * [1045859036] mem.c | 75: spifmem_add_var(): Storing as pointer #1 at 0x8049c18 (from 0x8049c18). * [1045859036] mem.c | 329: spifmem_strdup(): Variable pointer (0x8049a20) at mem_example.c:36 * [1045859036] mem.c | 246: spifmem_malloc(): 16 bytes requested at mem_example.c:36 - * [1045859036] mem.c | 74: memrec_add_var(): Adding variable (0x8049c40, 16 bytes) from mem_example.c:36. - * [1045859036] mem.c | 75: memrec_add_var(): Storing as pointer #2 at 0x8049c7c (from 0x8049c58). + * [1045859036] mem.c | 74: spifmem_add_var(): Adding variable (0x8049c40, 16 bytes) from mem_example.c:36. + * [1045859036] mem.c | 75: spifmem_add_var(): Storing as pointer #2 at 0x8049c7c (from 0x8049c58). * [1045859036] mem.c | 312: spifmem_free(): Variable dup (0x8049c40) at mem_example.c:39 - * [1045859036] mem.c | 94: memrec_find_var(): Found pointer #2 stored at 0x8049c7c (from 0x8049c58) - * [1045859036] mem.c | 113: memrec_rem_var(): Removing variable dup (0x8049c40) of size 16 + * [1045859036] mem.c | 94: spifmem_find_var(): Found pointer #2 stored at 0x8049c7c (from 0x8049c58) + * [1045859036] mem.c | 113: spifmem_rem_var(): Removing variable dup (0x8049c40) of size 16 * [1045859036] mem.c | 312: spifmem_free(): Variable dup ( (nil)) at mem_example.c:43 * [1045859036] mem.c | 319: spifmem_free(): ERROR: Caught attempt to free NULL pointer * [1045859036] mem.c | 268: spifmem_realloc(): Variable pointer (0x8049a20 -> 1000) at mem_example.c:46 - * [1045859036] mem.c | 94: memrec_find_var(): Found pointer #1 stored at 0x8049c58 (from 0x8049c58) - * [1045859036] mem.c | 132: memrec_chg_var(): Changing variable pointer (0x8049a20, 500 -> 0x8049c80, 1000) + * [1045859036] mem.c | 94: spifmem_find_var(): Found pointer #1 stored at 0x8049c58 (from 0x8049c58) + * [1045859036] mem.c | 132: spifmem_chg_var(): Changing variable pointer (0x8049a20, 500 -> 0x8049c80, 1000) * Dumping memory allocation table: * PTR: 1 pointers stored. * PTR: Pointer | Filename | Line | Address | Size | Offset | 00 01 02 03 04 05 06 07 | ASCII |