[patch] calling g_malloc & co via a vtable



Here is a patch that adds a vtable to g_malloc, g_malloc0, g_realloc and
g_free. It also adds g_try_malloc and g_try_realloc (not guaranteed to
return non-NULL).

Is any one interested? Any comments? Here are a few questions:

Has anyone tested the dmalloc.h stuff recently? It looks like it will
break some stuff that takes the address of g_free. Maybe i should rip it
out, or move it to a GAllocFunctions (but that would loose the file and
line no reporting).

The memory check and profiling has got a lot of ifdefs in it. Since they
are now in a vtable you could actually compile them in all the time. Or
just rip them out and let the application do such stuff by themselves.

One thing that i'd like to add, which is pretty usefull in embedded
systems is a memory pressure callback. It would be called when
malloc() fails to let the developer try to free some memory (flushing
caches etc). What do you think of this? It could be done by the user using
a custom GAllocFunctions, but then Gtk+ and Glib couldn't use it.

/ Alex

Index: glib.h
===================================================================
RCS file: /cvs/gnome/glib/glib.h,v
retrieving revision 1.204
diff -u -r1.204 glib.h
--- glib.h	2000/09/29 23:12:58	1.204
+++ glib.h	2000/10/02 15:24:06
@@ -1588,25 +1588,71 @@
 
 /* Memory allocation and debugging
  */
+typedef struct _GAllocFunctions GAllocFunctions;
+struct _GAllocFunctions
+{
+  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);
+};
+
+GLIB_VAR GAllocFunctions	g_alloc_functions_for_glib_use;
+
 #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)
+#define g_malloc(size)		((gpointer) MALLOC (size))
+#define g_try_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_try_realloc(mem,size)	((gpointer) REALLOC (mem, char, size))
+#define g_free(mem)		FREE (mem)
 
 #else /* !USE_DMALLOC */
 
-gpointer g_malloc      (gulong	  size);
-gpointer g_malloc0     (gulong	  size);
-gpointer g_realloc     (gpointer  mem,
-			gulong	  size);
-void	 g_free	       (gpointer  mem);
+#define G_ALLOC_OP(op, arglist) \
+    ((*g_alloc_functions_for_glib_use . op) arglist)
 
-#endif /* !USE_DMALLOC */
+#define g_malloc(size)		G_ALLOC_OP (malloc, ((size)))
+#define g_try_malloc(size)	G_ALLOC_OP (try_malloc, ((size)))
+#define g_malloc0(size)		G_ALLOC_OP (malloc0, ((size)))
+#define g_realloc(mem,size)	G_ALLOC_OP (realloc, ((mem), (size)))
+#define g_try_realloc(mem,size)	G_ALLOC_OP (try_realloc, ((mem), (size)))
+
+/* The address of g_free is often taken, so it must not be a macro */
+G_INLINE_FUNC void	g_free (gpointer mem);
+
+/* 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_allocator (GAllocFunctions *vtable);
 
-void	 g_mem_profile (void);
-void	 g_mem_check   (gpointer  mem);
+/* Enable the memory debugging facilities in glib. This function
+ * must be called before any g_malloc calls are made, otherwise
+ * malloc/free calls to the default and the debug allocators can become
+ * mixed up. For these functions to work you must compile glib with
+ * memory profiling and/or checking enabled.
+ */
+void	 g_mem_debug_enable (gboolean profile, gboolean check);
+void	 g_mem_profile      (void);
+void	 g_mem_check        (gpointer mem);
+
+/* Inline implementation for g_free */
+#if defined (G_CAN_INLINE) || defined (__G_UTILS_C__)
+G_INLINE_FUNC void
+g_free (gpointer mem)
+{
+  G_ALLOC_OP (free, ((mem)));
+}
+#endif  /* G_CAN_INLINE || __G_UTILS_C__ */
+
+
+#endif /* !USE_DMALLOC */
 
 /* 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/02 15:24:07
@@ -131,14 +131,35 @@
 static gint   g_mem_chunk_area_search  (GMemArea *a,
 					gchar    *addr);
 
+static gpointer g_malloc_default      (gulong size);
+static gpointer g_malloc0_default     (gulong size);
+static gpointer g_realloc_default     (gpointer mem,
+				       gulong   size);
+static gpointer g_try_malloc_default  (gulong size);
+static gpointer g_try_realloc_default (gpointer mem,
+				       gulong   size);
+static void     g_free_default        (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;
 
+#if defined(G_OS_WIN32) && defined(__GNUC__)
+__declspec(dllexport)
+#endif
+GAllocFunctions g_alloc_functions_for_glib_use = {
+  g_malloc_default,		/* malloc */
+  g_malloc0_default,		/* malloc0 */
+  g_realloc_default,		/* realloc */
+  g_try_malloc_default,		/* try_malloc */
+  g_try_realloc_default,	/* try_realloc */
+  g_free_default,		/* free */
+};
+
 #ifdef ENABLE_MEM_PROFILE
 static GMutex* mem_profile_lock;
+static gboolean enable_mem_profile = 0;
 static gulong allocations[MEM_PROFILE_TABLE_SIZE] = { 0 };
 static gulong allocated_mem = 0;
 static gulong freed_mem = 0;
@@ -147,47 +168,215 @@
   GPOINTER_TO_UINT (g_private_get (allocating_for_mem_chunk))
 #endif /* ENABLE_MEM_PROFILE */
 
+#ifdef ENABLE_MEM_CHECK
+static gboolean enable_mem_check = 0;
+#endif
+
+void
+g_mem_set_allocator (GAllocFunctions  *vtable)
+{
+  g_alloc_functions_for_glib_use = *vtable;
+}
 
-#ifndef USE_DMALLOC
 
-gpointer
-g_malloc (gulong size)
+static gpointer
+g_malloc_default (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 = (gpointer) malloc (size);
+  if (!p)
+    g_error ("could not allocate %ld bytes", size);
   
+  return p;
+}
+
+static gpointer
+g_malloc0_default (gulong size)
+{
+  gpointer p;
   
   if (size == 0)
     return NULL;
   
+  p = (gpointer) calloc (size, 1);
+  if (!p)
+    g_error ("could not allocate %ld bytes", size);
+  
+  return p;
+}
+
+static gpointer
+g_realloc_default (gpointer mem,
+	   gulong   size)
+{
+  gpointer p;
+  
+  if (size == 0)
+    {
+      g_free (mem);
+      return NULL;
+    }
   
+  if (!mem)
+    {
+#ifdef REALLOC_0_WORKS
+      p = (gpointer) realloc (NULL, size);
+#else /* !REALLOC_0_WORKS */
+      p = (gpointer) malloc (size);
+#endif /* !REALLOC_0_WORKS */
+    }
+  else
+    p = (gpointer) realloc (mem, size);
+  
+  if (!p)
+    g_error ("could not reallocate %lu bytes", (gulong) size);
+  
+  return p;
+}
+
+static gpointer
+g_try_malloc_default (gulong size)
+{
+  gpointer p;
+  
+  if (size == 0)
+    return NULL;
+  
+  p = (gpointer) malloc (size);
+  
+  return p;
+}
+
+static gpointer
+g_try_realloc_default (gpointer mem,
+	   gulong   size)
+{
+  gpointer p;
+  
+  if (size == 0)
+    {
+      g_free (mem);
+      return NULL;
+    }
+  
+  if (!mem)
+    {
+#ifdef REALLOC_0_WORKS
+      p = (gpointer) realloc (NULL, size);
+#else /* !REALLOC_0_WORKS */
+      p = (gpointer) malloc (size);
+#endif /* !REALLOC_0_WORKS */
+    }
+  else
+    p = (gpointer) realloc (mem, size);
+  
+  return p;
+}
+
+static void
+g_free_default (gpointer mem)
+{
+  if (mem)
+    free (mem);
+}
+
+/* Memory checking and profiling versions of the allocators: */
+
 #if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
+
+static gpointer
+g_malloc_debug (gulong size)
+{
+  gpointer p;
+  gulong *t;
+  
+  if (size == 0)
+    return NULL;
+  
   size += SIZEOF_LONG;
-#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
   
 #ifdef ENABLE_MEM_CHECK
-  size += SIZEOF_LONG;
+  if (enable_mem_check)
+    size += SIZEOF_LONG;
 #endif /* ENABLE_MEM_CHECK */
   
-  
   p = (gpointer) malloc (size);
   if (!p)
     g_error ("could not allocate %ld bytes", size);
   
   
 #ifdef ENABLE_MEM_CHECK
+  if (enable_mem_check) {
+    size -= SIZEOF_LONG;
+  
+    t = p;
+    p = ((guchar*) p + SIZEOF_LONG);
+    *t = 0;
+  }
+#endif /* ENABLE_MEM_CHECK */
+  
   size -= SIZEOF_LONG;
   
   t = p;
   p = ((guchar*) p + SIZEOF_LONG);
-  *t = 0;
+  *t = size;
+  
+#ifdef ENABLE_MEM_PROFILE
+  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)
+	allocations[size-1] += 1;
+      else
+	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 */
+  
+  return p;
+}
+
+static gpointer
+g_try_malloc_debug (gulong size)
+{
+  gpointer p;
+  gulong *t;
+  
+  if (size == 0)
+    return NULL;
+  
+  size += SIZEOF_LONG;
+  
+#ifdef ENABLE_MEM_CHECK
+  if (enable_mem_check)
+    size += SIZEOF_LONG;
 #endif /* ENABLE_MEM_CHECK */
   
-#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
+  p = (gpointer) malloc (size);
+  if (!p) 
+    return NULL;
+  
+  
+#ifdef ENABLE_MEM_CHECK
+  if (enable_mem_check) {
+    size -= SIZEOF_LONG;
+  
+    t = p;
+    p = ((guchar*) p + SIZEOF_LONG);
+    *t = 0;
+  }
+#endif /* ENABLE_MEM_CHECK */
+  
   size -= SIZEOF_LONG;
   
   t = p;
@@ -195,101 +384,90 @@
   *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)
+	allocations[size-1] += 1;
+      else
+	allocations[MEM_PROFILE_TABLE_SIZE - 1] += 1;
+      allocated_mem += size;
 #  ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
-  }
+    }
 #  endif
-  g_mutex_unlock (mem_profile_lock);
+    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;
+  if (enable_mem_check)
+    size += SIZEOF_LONG;
 #endif /* ENABLE_MEM_CHECK */
   
-  
   p = (gpointer) calloc (size, 1);
   if (!p)
     g_error ("could not allocate %ld bytes", size);
   
-  
 #ifdef ENABLE_MEM_CHECK
-  size -= SIZEOF_LONG;
+  if (enable_mem_check) {
+    size -= SIZEOF_LONG;
   
-  t = p;
-  p = ((guchar*) p + SIZEOF_LONG);
-  *t = 0;
+    t = p;
+    p = ((guchar*) p + SIZEOF_LONG);
+    *t = 0;
+  }
 #endif /* ENABLE_MEM_CHECK */
   
-#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
+#ifdef ENABLE_MEM_PROFILE
+  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))
+	allocations[size-1] += 1;
+      else
+	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 */
-  
+#endif /* ENABLE_MEM_PROFILE */
   
   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)
     {
@@ -299,12 +477,11 @@
     }
   
   
-#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;
+  if (enable_mem_check)
+    size += SIZEOF_LONG;
 #endif /* ENABLE_MEM_CHECK */
   
   
@@ -318,21 +495,23 @@
     }
   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);
+      if (enable_mem_profile) {
+	g_mutex_lock (mem_profile_lock);
+	freed_mem += *t;
+	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 ("trying to realloc freed memory\n");
-      mem = t;
+      if (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 */
       
       p = (gpointer) realloc (mem, size);
@@ -343,14 +522,111 @@
   
   
 #ifdef ENABLE_MEM_CHECK
+  if (enable_mem_check) {
+    size -= SIZEOF_LONG;
+  
+    t = p;
+    p = ((guchar*) p + SIZEOF_LONG);
+    *t = 0;
+  }
+#endif /* ENABLE_MEM_CHECK */
+  
   size -= SIZEOF_LONG;
   
   t = p;
   p = ((guchar*) p + SIZEOF_LONG);
-  *t = 0;
+  *t = size;
+  
+#ifdef ENABLE_MEM_PROFILE
+  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))
+	allocations[size-1] += 1;
+      else
+	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 */
+  
+  return p;
+}
+
+
+static gpointer
+g_try_realloc_debug (gpointer mem,
+		     gulong   size)
+{
+  gpointer p;
+  gulong *t;
+  
+  if (size == 0)
+    {
+      g_free (mem);
+    
+      return NULL;
+    }
+  
+  
+  size += SIZEOF_LONG;
+  
+#ifdef ENABLE_MEM_CHECK
+  if (enable_mem_check)
+    size += SIZEOF_LONG;
 #endif /* ENABLE_MEM_CHECK */
   
-#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
+  
+  if (!mem)
+    {
+#ifdef REALLOC_0_WORKS
+      p = (gpointer) realloc (NULL, size);
+#else /* !REALLOC_0_WORKS */
+      p = (gpointer) malloc (size);
+#endif /* !REALLOC_0_WORKS */
+    }
+  else
+    {
+      t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
+#ifdef ENABLE_MEM_PROFILE
+      if (enable_mem_profile) {
+	g_mutex_lock (mem_profile_lock);
+	freed_mem += *t;
+	g_mutex_unlock (mem_profile_lock);
+      }
+#endif /* ENABLE_MEM_PROFILE */
+      mem = t;
+      
+#ifdef 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;
+      }
+#endif /* ENABLE_MEM_CHECK */
+      
+      p = (gpointer) realloc (mem, size);
+    }
+  
+  if (!p)
+    return NULL;
+  
+#ifdef ENABLE_MEM_CHECK
+  if (enable_mem_check) {
+    size -= SIZEOF_LONG;
+  
+    t = p;
+    p = ((guchar*) p + SIZEOF_LONG);
+    *t = 0;
+  }
+#endif /* ENABLE_MEM_CHECK */
+  
   size -= SIZEOF_LONG;
   
   t = p;
@@ -358,63 +634,89 @@
   *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))
+	allocations[size-1] += 1;
+      else
+	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;
 }
 
-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);
+#ifdef ENABLE_MEM_PROFILE
+      if (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;
+      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);
+	memset ((guchar*) mem + 2 * SIZEOF_LONG, 0, size);
+      }
 #else /* ENABLE_MEM_CHECK */
       free (mem);
 #endif /* ENABLE_MEM_CHECK */
     }
 }
 
-#endif /* ! USE_DMALLOC */
+#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
+
+void
+g_mem_debug_enable (gboolean profile, gboolean check)
+{
+#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
 
+  GAllocFunctions debug_alloc = {
+    g_malloc_debug,		/* malloc */
+    g_malloc0_debug,		/* malloc0 */
+    g_realloc_debug,		/* realloc */
+    g_try_malloc_debug,		/* try_malloc */
+    g_try_realloc_debug,	/* try_realloc */
+    g_free_debug,		/* free */
+  };
+
+  g_mem_set_alloc(&debug_alloc);
+  
+#ifdef ENABLE_MEM_PROFILE
+  enable_mem_profile = profile;
+#endif /* ENABLE_MEM_PROFILE */
+#ifdef ENABLE_MEM_CHECK
+  enable_mem_check = check;
+#endif /* ENABLE_MEM_PROFILE */
+  
+#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
+}
 
 void
 g_mem_profile (void)
@@ -425,6 +727,9 @@
   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];
@@ -452,6 +757,12 @@
 {
 #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);
   






[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]