g_malloc vtable patch take two
- From: Alexander Larsson <alla lysator liu se>
- To: gtk-devel-list gnome org
- Subject: g_malloc vtable patch take two
- Date: Thu, 12 Oct 2000 17:02:39 +0200 (CEST)
Ok, here is a new version of the patch, ready for some doofus to screw up
with. This time i removed the dmalloc support and removed the ifdefs
around the memory profiling and checking code. I also added checks so that
g_mem_set_vtable() warns and fails if any of the default allocators has
been used before the call.
This one is pretty minimal, and I hope people not into memory vtables will
not get to offended by it. I think it is as small it can get, while still
having sufficient power to do some ugly out-of-mem stuff if you really
want. Also, the code doesn't mention out-of-mem situations or callbacks,
so your typical run-of-the-mill doofus might not get the idea to use it
for such things at all.
/ Alex
Index: gmem.h
===================================================================
RCS file: /cvs/gnome/glib/gmem.h,v
retrieving revision 1.1
diff -u -r1.1 gmem.h
--- gmem.h 2000/10/12 11:52:07 1.1
+++ gmem.h 2000/10/12 14:36:06
@@ -29,12 +29,6 @@
#include <gtypes.h>
-/* optionally feature DMALLOC memory allocation debugger
- */
-#ifdef USE_DMALLOC
-#include "dmalloc.h"
-#endif
-
G_BEGIN_DECLS
typedef struct _GAllocator GAllocator;
@@ -45,18 +39,12 @@
* in order to avoid compiler warnings. (Makes the code neater).
*/
-#ifdef __DMALLOC_H__
-# define g_new(type, count) (ALLOC (type, count))
-# define g_new0(type, count) (CALLOC (type, count))
-# define g_renew(type, mem, count) (REALLOC (mem, type, count))
-#else /* __DMALLOC_H__ */
-# define g_new(type, count) \
+#define g_new(type, count) \
((type *) g_malloc ((unsigned) sizeof (type) * (count)))
-# define g_new0(type, count) \
+#define g_new0(type, count) \
((type *) g_malloc0 ((unsigned) sizeof (type) * (count)))
-# define g_renew(type, mem, count) \
+#define g_renew(type, mem, count) \
((type *) g_realloc (mem, (unsigned) sizeof (type) * (count)))
-#endif /* __DMALLOC_H__ */
#define g_mem_chunk_create(type, pre_alloc, alloc_type) ( \
g_mem_chunk_new (#type " mem chunks (" #pre_alloc ")", \
@@ -76,25 +64,48 @@
/* Memory allocation and debugging
*/
-#ifdef USE_DMALLOC
-
-#define g_malloc(size) ((gpointer) MALLOC (size))
-#define g_malloc0(size) ((gpointer) CALLOC (char, size))
-#define g_realloc(mem,size) ((gpointer) REALLOC (mem, char, size))
-#define g_free(mem) FREE (mem)
-
-#else /* !USE_DMALLOC */
+typedef struct _GMemFunctions GMemFunctions;
+struct _GMemFunctions
+{
+ gpointer (*malloc) (gulong size);
+ gpointer (*malloc0) (gulong size);
+ gpointer (*realloc) (gpointer mem, gulong size);
+ gpointer (*try_malloc) (gulong size);
+ gpointer (*try_realloc) (gpointer mem, gulong size);
+ void (*free) (gpointer mem);
+};
+
+typedef enum
+{
+ G_MEM_PROFILE = 1 << 0,
+ G_MEM_CHECK = 1 << 1
+} GMemDebugFlags;
gpointer g_malloc (gulong size);
+gpointer g_try_malloc (gulong size);
gpointer g_malloc0 (gulong size);
gpointer g_realloc (gpointer mem,
gulong size);
+gpointer g_try_realloc (gpointer mem,
+ gulong size);
void g_free (gpointer mem);
-#endif /* !USE_DMALLOC */
+/* Set the allocator implementation for glib. Use this if you want
+ * glib to use a different malloc/free implementation. This function
+ * must be called before any g_malloc calls are made, otherwise
+ * malloc/free calls to the default and the new allocators can become
+ * mixed up.
+ */
+void g_mem_set_vtable (const GMemFunctions *vtable);
-void g_mem_profile (void);
-void g_mem_check (gpointer mem);
+/* Enable the memory debugging facilities in glib. This function
+ * must be called only once, and before any g_malloc calls are made,
+ * otherwise malloc/free calls to the default and the debug allocators
+ * can become mixed up.
+ */
+void g_mem_debug_enable (GMemDebugFlags flags);
+void g_mem_profile (void);
+void g_mem_check (gpointer mem);
/* Generic allocators
*/
Index: gmem.c
===================================================================
RCS file: /cvs/gnome/glib/gmem.c,v
retrieving revision 1.23
diff -u -r1.23 gmem.c
--- gmem.c 2000/09/25 21:28:14 1.23
+++ gmem.c 2000/10/12 14:36:06
@@ -36,29 +36,24 @@
#include <string.h>
#include "glib.h"
-/* #define ENABLE_MEM_PROFILE */
-/* #define ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS */
-/* #define ENABLE_MEM_CHECK */
#define MEM_PROFILE_TABLE_SIZE 8192
/*
* This library can check for some attempts to do illegal things to
- * memory (ENABLE_MEM_CHECK), and can do profiling
- * (ENABLE_MEM_PROFILE). Both features are implemented by storing
- * words before the start of the memory chunk.
+ * memory, and can do profiling. Both features are implemented by
+ * storing words before the start of the memory chunk.
*
* The first, at offset -2*SIZEOF_LONG, is used only if
- * ENABLE_MEM_CHECK is set, and stores 0 after the memory has been
+ * mem checking is enabled, and stores 0 after the memory has been
* allocated and 1 when it has been freed. The second, at offset
- * -SIZEOF_LONG, is used if either flag is set and stores the size of
- * the block.
+ * -SIZEOF_LONG stores the size of the block.
*
- * The MEM_CHECK flag is checked when memory is realloc'd and free'd,
+ * The mem check flag is checked when memory is realloc'd and free'd,
* and it can be explicitly checked before using a block by calling
* g_mem_check().
*/
-#if defined(ENABLE_MEM_PROFILE) && defined(ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS)
+#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
#define ENTER_MEM_CHUNK_ROUTINE() \
g_private_set (allocating_for_mem_chunk, \
g_private_get (allocating_for_mem_chunk) + 1)
@@ -132,180 +127,381 @@
gchar *addr);
+static gpointer g_malloc_initial (gulong size);
+static gpointer g_malloc0_initial (gulong size);
+static gpointer g_realloc_initial (gpointer mem,
+ gulong size);
+static void g_free_initial (gpointer mem);
+
+static gpointer g_malloc_real (gulong size);
+static gpointer g_malloc0_real (gulong size);
+static gpointer g_realloc_real (gpointer mem,
+ gulong size);
+static void g_free_real (gpointer mem);
+
+static gpointer g_malloc_debug (gulong size);
+static gpointer g_malloc0_debug (gulong size);
+static gpointer g_realloc_debug (gpointer mem,
+ gulong size);
+static void g_free_debug (gpointer mem);
+
+
/* here we can't use StaticMutexes, as they depend upon a working
* g_malloc, the same holds true for StaticPrivate */
static GMutex* mem_chunks_lock = NULL;
static GRealMemChunk *mem_chunks = NULL;
+
+GMemFunctions g_mem_vtable = {
+ g_malloc_initial, /* malloc */
+ g_malloc0_initial, /* malloc0 */
+ g_realloc_initial, /* realloc */
+ g_malloc_initial, /* try_malloc */
+ g_realloc_initial, /* try_realloc */
+ g_free_initial /* free */
+};
-#ifdef ENABLE_MEM_PROFILE
+/* Data for memory profiling: */
static GMutex* mem_profile_lock;
-static gulong allocations[MEM_PROFILE_TABLE_SIZE] = { 0 };
+static gulong *allocations = NULL;
+static gulong *total_allocations = NULL;
static gulong allocated_mem = 0;
static gulong freed_mem = 0;
+
+#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
static GPrivate* allocating_for_mem_chunk = NULL;
#define IS_IN_MEM_CHUNK_ROUTINE() \
GPOINTER_TO_UINT (g_private_get (allocating_for_mem_chunk))
-#endif /* ENABLE_MEM_PROFILE */
+#endif
+static gboolean enable_mem_profile = FALSE;
+static gboolean enable_mem_check = FALSE;
-#ifndef USE_DMALLOC
+static gboolean malloc_used = FALSE;
+void
+g_mem_set_vtable (const GMemFunctions *vtable)
+{
+ if (malloc_used)
+ g_warning ("Trying to set glib memory vtable after g_malloc has been called, ignored\n");
+ else
+ g_mem_vtable = *vtable;
+}
+
+static void
+g_mem_set_default_vtable(void)
+{
+ GMemFunctions default_vtable = {
+ g_malloc_real, /* malloc */
+ g_malloc0_real, /* malloc0 */
+ g_realloc_real, /* realloc */
+ g_malloc_real, /* try_malloc */
+ g_realloc_real, /* try_realloc */
+ g_free_real /* free */
+ };
+
+ g_mem_set_vtable (&default_vtable);
+}
+
+void
+g_mem_debug_enable (GMemDebugFlags flags)
+{
+
+ GMemFunctions debug_vtable = {
+ g_malloc_debug, /* malloc */
+ g_malloc0_debug, /* malloc0 */
+ g_realloc_debug, /* realloc */
+ g_malloc_debug, /* try_malloc */
+ g_realloc_debug, /* try_realloc */
+ g_free_debug, /* free */
+ };
+
+ if (flags)
+ g_mem_set_vtable (&debug_vtable);
+
+ enable_mem_profile = flags & G_MEM_PROFILE;
+ enable_mem_check = flags & G_MEM_CHECK;
+
+ if (enable_mem_profile)
+ {
+ /* Use calloc here instead of g_malloc0, so that the malloc
+ * profiling code doesn't show up in the profile.
+ */
+ allocations = calloc (MEM_PROFILE_TABLE_SIZE, sizeof(gulong));
+ total_allocations = calloc (MEM_PROFILE_TABLE_SIZE, sizeof(gulong));
+
+ if (!allocations || !total_allocations)
+ enable_mem_profile = FALSE;
+ }
+}
+
gpointer
g_malloc (gulong size)
{
gpointer p;
+ if (size == 0)
+ return NULL;
-#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
- gulong *t;
-#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
+ p = g_mem_vtable.malloc (size);
+ if (!p)
+ g_error ("could not allocate %ld bytes", size);
+ return p;
+}
+
+gpointer
+g_malloc0 (gulong size)
+{
+ gpointer p;
if (size == 0)
return NULL;
+ p = g_mem_vtable.malloc0 (size);
+
+ if (!p)
+ g_error ("could not allocate %ld bytes", size);
-#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
- size += SIZEOF_LONG;
-#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
+ return p;
+}
+
+gpointer
+g_realloc (gpointer mem,
+ gulong size)
+{
+ gpointer p;
+
+ if (size == 0)
+ {
+ g_free (mem);
+ return NULL;
+ }
+
+ p = g_mem_vtable.realloc (mem, size);
+
+ if (!p)
+ g_error ("could not reallocate %lu bytes", (gulong) size);
-#ifdef ENABLE_MEM_CHECK
+ return p;
+}
+
+gpointer
+g_try_malloc (gulong size)
+{
+ if (size == 0)
+ return NULL;
+
+ return g_mem_vtable.try_malloc (size);
+}
+
+gpointer
+g_try_realloc (gpointer mem,
+ gulong size)
+{
+ if (size == 0)
+ {
+ g_free (mem);
+ return NULL;
+ }
+
+ return g_mem_vtable.try_realloc (mem, size);
+}
+
+void
+g_free (gpointer mem)
+{
+ if (mem)
+ g_mem_vtable.free (mem);
+}
+
+static gpointer
+g_malloc_real (gulong size)
+{
+ return (gpointer) malloc (size);
+}
+
+static gpointer
+g_malloc0_real (gulong size)
+{
+ return (gpointer) calloc (size, 1);
+}
+
+static gpointer
+g_realloc_real (gpointer mem,
+ gulong size)
+{
+ if (!mem)
+ {
+#ifdef REALLOC_0_WORKS
+ return (gpointer) realloc (NULL, size);
+#else /* !REALLOC_0_WORKS */
+ return (gpointer) malloc (size);
+#endif /* !REALLOC_0_WORKS */
+ }
+ else
+ return (gpointer) realloc (mem, size);
+}
+
+static void
+g_free_real (gpointer mem)
+{
+ free (mem);
+}
+
+static gpointer
+g_malloc_initial (gulong size)
+{
+ g_mem_set_default_vtable ();
+ malloc_used = TRUE;
+ return g_malloc (size);
+}
+
+static gpointer
+g_malloc0_initial (gulong size)
+{
+ g_mem_set_default_vtable ();
+ malloc_used = TRUE;
+ return g_malloc0 (size);
+}
+
+static gpointer
+g_realloc_initial (gpointer mem,
+ gulong size)
+{
+ g_mem_set_default_vtable ();
+ malloc_used = TRUE;
+ return g_realloc (mem, size);
+}
+
+static void
+g_free_initial (gpointer mem)
+{
+ g_mem_set_default_vtable ();
+ malloc_used = TRUE;
+ g_free (mem);
+}
+
+/* Memory checking and profiling versions of the allocators: */
+
+static gpointer
+g_malloc_debug (gulong size)
+{
+ gpointer p;
+ gulong *t;
+
size += SIZEOF_LONG;
-#endif /* ENABLE_MEM_CHECK */
+ if (enable_mem_check)
+ size += SIZEOF_LONG;
p = (gpointer) malloc (size);
if (!p)
- g_error ("could not allocate %ld bytes", size);
-
+ return NULL;
-#ifdef ENABLE_MEM_CHECK
- size -= SIZEOF_LONG;
+ if (enable_mem_check) {
+ size -= SIZEOF_LONG;
- t = p;
- p = ((guchar*) p + SIZEOF_LONG);
- *t = 0;
-#endif /* ENABLE_MEM_CHECK */
+ t = p;
+ p = ((guchar*) p + SIZEOF_LONG);
+ *t = 0;
+ }
-#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
size -= SIZEOF_LONG;
t = p;
p = ((guchar*) p + SIZEOF_LONG);
*t = size;
-#ifdef ENABLE_MEM_PROFILE
- g_mutex_lock (mem_profile_lock);
-# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
- if(!IS_IN_MEM_CHUNK_ROUTINE()) {
-# endif
- if (size <= MEM_PROFILE_TABLE_SIZE - 1)
- allocations[size-1] += 1;
- else
- allocations[MEM_PROFILE_TABLE_SIZE - 1] += 1;
- allocated_mem += size;
-# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
+ if (enable_mem_profile) {
+ g_mutex_lock (mem_profile_lock);
+#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
+ if(!IS_IN_MEM_CHUNK_ROUTINE()) {
+#endif
+ if (size <= MEM_PROFILE_TABLE_SIZE - 1)
+ {
+ total_allocations[size-1] += 1;
+ allocations[size-1] += 1;
+ }
+ else
+ {
+ total_allocations[MEM_PROFILE_TABLE_SIZE - 1] += 1;
+ allocations[MEM_PROFILE_TABLE_SIZE - 1] += 1;
+ }
+ allocated_mem += size;
+#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
+ }
+#endif
+ g_mutex_unlock (mem_profile_lock);
}
-# endif
- g_mutex_unlock (mem_profile_lock);
-#endif /* ENABLE_MEM_PROFILE */
-#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
-
return p;
}
-gpointer
-g_malloc0 (gulong size)
+static gpointer
+g_malloc0_debug (gulong size)
{
gpointer p;
-
-
-#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
gulong *t;
-#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
-
-
- if (size == 0)
- return NULL;
-
-#if defined (ENABLE_MEM_PROFILE) || defined (ENABLE_MEM_CHECK)
size += SIZEOF_LONG;
-#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
-#ifdef ENABLE_MEM_CHECK
- size += SIZEOF_LONG;
-#endif /* ENABLE_MEM_CHECK */
-
+ if (enable_mem_check)
+ size += SIZEOF_LONG;
p = (gpointer) calloc (size, 1);
if (!p)
- g_error ("could not allocate %ld bytes", size);
-
+ return NULL;
-#ifdef ENABLE_MEM_CHECK
- size -= SIZEOF_LONG;
+ if (enable_mem_check) {
+ size -= SIZEOF_LONG;
- t = p;
- p = ((guchar*) p + SIZEOF_LONG);
- *t = 0;
-#endif /* ENABLE_MEM_CHECK */
+ t = p;
+ p = ((guchar*) p + SIZEOF_LONG);
+ *t = 0;
+ }
-#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
size -= SIZEOF_LONG;
t = p;
p = ((guchar*) p + SIZEOF_LONG);
*t = size;
-# ifdef ENABLE_MEM_PROFILE
- g_mutex_lock (mem_profile_lock);
-# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
- if(!IS_IN_MEM_CHUNK_ROUTINE()) {
-# endif
- if (size <= (MEM_PROFILE_TABLE_SIZE - 1))
- allocations[size-1] += 1;
- else
- allocations[MEM_PROFILE_TABLE_SIZE - 1] += 1;
- allocated_mem += size;
-# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
+ if (enable_mem_profile) {
+ g_mutex_lock (mem_profile_lock);
+#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
+ if(!IS_IN_MEM_CHUNK_ROUTINE()) {
+#endif
+ if (size <= MEM_PROFILE_TABLE_SIZE - 1)
+ {
+ total_allocations[size-1] += 1;
+ allocations[size-1] += 1;
+ }
+ else
+ {
+ total_allocations[MEM_PROFILE_TABLE_SIZE - 1] += 1;
+ allocations[MEM_PROFILE_TABLE_SIZE - 1] += 1;
+ }
+ allocated_mem += size;
+#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
+ }
+#endif
+ g_mutex_unlock (mem_profile_lock);
}
-# endif
- g_mutex_unlock (mem_profile_lock);
-# endif /* ENABLE_MEM_PROFILE */
-#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
-
return p;
}
-gpointer
-g_realloc (gpointer mem,
- gulong size)
+static gpointer
+g_realloc_debug (gpointer mem,
+ gulong size)
{
gpointer p;
-
-#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
gulong *t;
-#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
-
-
- if (size == 0)
- {
- g_free (mem);
-
- return NULL;
- }
-
-#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
size += SIZEOF_LONG;
-#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
-#ifdef ENABLE_MEM_CHECK
- size += SIZEOF_LONG;
-#endif /* ENABLE_MEM_CHECK */
+ if (enable_mem_check)
+ size += SIZEOF_LONG;
if (!mem)
@@ -318,148 +514,172 @@
}
else
{
-#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
-#ifdef ENABLE_MEM_PROFILE
- g_mutex_lock (mem_profile_lock);
- freed_mem += *t;
- g_mutex_unlock (mem_profile_lock);
-#endif /* ENABLE_MEM_PROFILE */
+ if (enable_mem_profile) {
+ g_mutex_lock (mem_profile_lock);
+ freed_mem += *t;
+ if (*t <= (MEM_PROFILE_TABLE_SIZE - 1))
+ allocations[*t-1] -= 1;
+ else
+ allocations[MEM_PROFILE_TABLE_SIZE - 1] -= 1;
+ g_mutex_unlock (mem_profile_lock);
+ }
mem = t;
-#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
-#ifdef ENABLE_MEM_CHECK
- t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
- if (*t >= 1)
- g_warning ("trying to realloc freed memory\n");
- mem = t;
-#endif /* ENABLE_MEM_CHECK */
+ if (enable_mem_check) {
+ t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
+ if (*t >= 1)
+ g_warning ("trying to realloc freed memory\n");
+ mem = t;
+ }
p = (gpointer) realloc (mem, size);
}
if (!p)
- g_error ("could not reallocate %lu bytes", (gulong) size);
+ return NULL;
-#ifdef ENABLE_MEM_CHECK
- size -= SIZEOF_LONG;
+ if (enable_mem_check) {
+ size -= SIZEOF_LONG;
- t = p;
- p = ((guchar*) p + SIZEOF_LONG);
- *t = 0;
-#endif /* ENABLE_MEM_CHECK */
+ t = p;
+ p = ((guchar*) p + SIZEOF_LONG);
+ *t = 0;
+ }
-#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
size -= SIZEOF_LONG;
t = p;
p = ((guchar*) p + SIZEOF_LONG);
*t = size;
-#ifdef ENABLE_MEM_PROFILE
- g_mutex_lock (mem_profile_lock);
+ if (enable_mem_profile) {
+ g_mutex_lock (mem_profile_lock);
#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
- if(!IS_IN_MEM_CHUNK_ROUTINE()) {
+ if(!IS_IN_MEM_CHUNK_ROUTINE()) {
#endif
- if (size <= (MEM_PROFILE_TABLE_SIZE - 1))
- allocations[size-1] += 1;
- else
- allocations[MEM_PROFILE_TABLE_SIZE - 1] += 1;
- allocated_mem += size;
+ if (size <= MEM_PROFILE_TABLE_SIZE - 1)
+ {
+ total_allocations[size-1] += 1;
+ allocations[size-1] += 1;
+ }
+ else
+ {
+ total_allocations[MEM_PROFILE_TABLE_SIZE - 1] += 1;
+ allocations[MEM_PROFILE_TABLE_SIZE - 1] += 1;
+ }
+ allocated_mem += size;
#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
- }
+ }
#endif
- g_mutex_unlock (mem_profile_lock);
-#endif /* ENABLE_MEM_PROFILE */
-#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
-
+ g_mutex_unlock (mem_profile_lock);
+ }
return p;
}
-void
-g_free (gpointer mem)
+static void
+g_free_debug (gpointer mem)
{
- if (mem)
- {
-#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
- gulong *t;
- gulong size;
-#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
-
-#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
- t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
- size = *t;
-#ifdef ENABLE_MEM_PROFILE
- g_mutex_lock (mem_profile_lock);
- freed_mem += size;
- g_mutex_unlock (mem_profile_lock);
-#endif /* ENABLE_MEM_PROFILE */
- mem = t;
-#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
-
-#ifdef ENABLE_MEM_CHECK
- t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
- if (*t >= 1)
- g_warning ("freeing previously freed (%lu times) memory\n", *t);
- *t += 1;
- mem = t;
+ gulong *t;
+ gulong size;
- memset ((guchar*) mem + 2 * SIZEOF_LONG, 0, size);
-#else /* ENABLE_MEM_CHECK */
- free (mem);
-#endif /* ENABLE_MEM_CHECK */
- }
+ t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
+ size = *t;
+ if (enable_mem_profile) {
+ g_mutex_lock (mem_profile_lock);
+ freed_mem += size;
+ if (size <= (MEM_PROFILE_TABLE_SIZE - 1))
+ allocations[size-1] -= 1;
+ else
+ allocations[MEM_PROFILE_TABLE_SIZE - 1] -= 1;
+ g_mutex_unlock (mem_profile_lock);
+ }
+ mem = t;
+
+ if (enable_mem_check) {
+ t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
+ if (*t >= 1)
+ g_warning ("freeing previously freed (%lu times) memory\n", *t);
+ *t += 1;
+ mem = t;
+
+ memset ((guchar*) mem + 2 * SIZEOF_LONG, 0, size);
+ }
+ free (mem);
}
-#endif /* ! USE_DMALLOC */
-
-
void
g_mem_profile (void)
{
-#ifdef ENABLE_MEM_PROFILE
gint i;
gulong local_allocations[MEM_PROFILE_TABLE_SIZE];
+ gulong local_total_allocations[MEM_PROFILE_TABLE_SIZE];
gulong local_allocated_mem;
gulong local_freed_mem;
+ if (!enable_mem_profile)
+ g_warning("mem: g_mem_profile called with memory profiling disabled\n");
+
g_mutex_lock (mem_profile_lock);
for (i = 0; i < MEM_PROFILE_TABLE_SIZE; i++)
- local_allocations[i] = allocations[i];
+ {
+ local_allocations[i] = allocations[i];
+ local_total_allocations[i] = total_allocations[i];
+ }
local_allocated_mem = allocated_mem;
local_freed_mem = freed_mem;
g_mutex_unlock (mem_profile_lock);
for (i = 0; i < (MEM_PROFILE_TABLE_SIZE - 1); i++)
- if (local_allocations[i] > 0)
- g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
- "%lu allocations of %d bytes", local_allocations[i], i + 1);
-
- if (local_allocations[MEM_PROFILE_TABLE_SIZE - 1] > 0)
- g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
- "%lu allocations of greater than %d bytes",
- local_allocations[MEM_PROFILE_TABLE_SIZE - 1], MEM_PROFILE_TABLE_SIZE - 1);
+ if (local_total_allocations[i] > 0)
+ {
+ if (local_allocations [i] > 0)
+ g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
+ "%lu allocations of %d bytes (%ld not freed)", local_total_allocations[i], i + 1,
+ local_allocations[i]);
+ else
+ g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
+ "%lu allocations of %d bytes", local_total_allocations[i], i + 1);
+ }
+
+ if (local_total_allocations[MEM_PROFILE_TABLE_SIZE - 1] > 0)
+ {
+ if (local_allocations[MEM_PROFILE_TABLE_SIZE - 1] > 0)
+ g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
+ "%lu allocations of greater than %d bytes (%ld not freed)",
+ local_total_allocations[MEM_PROFILE_TABLE_SIZE - 1], MEM_PROFILE_TABLE_SIZE - 1,
+ local_allocations[MEM_PROFILE_TABLE_SIZE - 1]);
+ else
+ g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
+ "%lu allocations of greater than %d bytes",
+ local_total_allocations[MEM_PROFILE_TABLE_SIZE - 1], MEM_PROFILE_TABLE_SIZE - 1);
+ }
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes allocated", local_allocated_mem);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes freed", local_freed_mem);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes in use", local_allocated_mem - local_freed_mem);
-#endif /* ENABLE_MEM_PROFILE */
}
void
g_mem_check (gpointer mem)
{
-#ifdef ENABLE_MEM_CHECK
gulong *t;
+ if (!enable_mem_check)
+ {
+ g_warning("mem: g_mem_check called with memory checking disabled\n");
+ return;
+ }
+
t = (gulong*) ((guchar*) mem - SIZEOF_LONG - SIZEOF_LONG);
if (*t >= 1)
g_warning ("mem: 0x%08lx has been freed %lu times\n", (gulong) mem, *t);
-#endif /* ENABLE_MEM_CHECK */
}
+
+
GMemChunk*
g_mem_chunk_new (gchar *name,
gint atom_size,
@@ -1011,8 +1231,8 @@
g_mem_init (void)
{
mem_chunks_lock = g_mutex_new();
-#ifdef ENABLE_MEM_PROFILE
- mem_profile_lock = g_mutex_new();
- allocating_for_mem_chunk = g_private_new(NULL);
+ mem_profile_lock = g_mutex_new ();
+#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
+ allocating_for_mem_chunk = g_private_new (NULL);
#endif
}
Index: configure.in
===================================================================
RCS file: /cvs/gnome/glib/configure.in,v
retrieving revision 1.153
diff -u -r1.153 configure.in
--- configure.in 2000/10/12 11:52:07 1.153
+++ configure.in 2000/10/12 14:36:05
@@ -101,8 +101,6 @@
dnl declare --enable-* args and collect ac_help strings
AC_ARG_ENABLE(debug, [ --enable-debug=[no/minimum/yes] turn on debugging [default=$debug_default]],,enable_debug=$debug_default)
AC_ARG_ENABLE(msg-prefix, [ --enable-msg-prefix turn on program name and PID prefixing of messages and warnings],,enable_msg_prefix=no)
-AC_ARG_ENABLE(mem_check, [ --enable-mem-check turn on malloc/free sanity checking [default=no]],,enable_mem_check=no)
-AC_ARG_ENABLE(mem_profile, [ --enable-mem-profile turn on malloc profiling atexit [default=no]],,enable_mem_profile=no)
AC_ARG_ENABLE(gc_friendly, [ --enable-gc-friendly turn on garbage collector friendliness [default=no]],,enable_gc_friendly=no)
AC_ARG_ENABLE(ansi, [ --enable-ansi turn on strict ansi [default=no]],
, enable_ansi=no)
@@ -111,24 +109,6 @@
if test "x$enable_threads" != "xyes"; then
enable_threads=no
-fi
-
-AC_MSG_CHECKING(whether to enable memory checking)
-if test "x$enable_mem_check" = "xyes"; then
- AC_DEFINE(ENABLE_MEM_CHECK, 1)
- AC_SUBST(ENABLE_MEM_CHECK)
- AC_MSG_RESULT(yes)
-else
- AC_MSG_RESULT(no)
-fi
-
-AC_MSG_CHECKING(whether to enable memory profiling)
-if test "x$enable_mem_profile" = "xyes"; then
- AC_DEFINE(ENABLE_MEM_PROFILE, 1)
- AC_SUBST(ENABLE_MEM_PROFILE)
- AC_MSG_RESULT(yes)
-else
- AC_MSG_RESULT(no)
fi
AC_MSG_CHECKING(whether to enable garbage collector friendliness)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]