locks: drop _INIT macros
[platform/upstream/glib.git] / glib / gmem.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GLib Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 /* 
28  * MT safe
29  */
30
31 #include "config.h"
32
33 #include "gmem.h"
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <signal.h>
38
39 #include "gslice.h"
40 #include "gbacktrace.h"
41 #include "gtestutils.h"
42 #include "gthread.h"
43 #include "glib_trace.h"
44 #include "glib-ctor.h"
45
46
47 #define MEM_PROFILE_TABLE_SIZE 4096
48
49
50 /* notes on macros:
51  * having G_DISABLE_CHECKS defined disables use of glib_mem_profiler_table and
52  * g_mem_profile().
53  * REALLOC_0_WORKS is defined if g_realloc (NULL, x) works.
54  * SANE_MALLOC_PROTOS is defined if the systems malloc() and friends functions
55  * match the corresponding GLib prototypes, keep configure.ac and gmem.h in sync here.
56  * g_mem_gc_friendly is TRUE, freed memory should be 0-wiped.
57  */
58
59 #ifdef ENABLE_GC_FRIENDLY_DEFAULT
60 gboolean g_mem_gc_friendly = TRUE;
61 #else
62 /**
63  * g_mem_gc_friendly:
64  * 
65  * This variable is %TRUE if the <envar>G_DEBUG</envar> environment variable
66  * includes the key <link linkend="G_DEBUG">gc-friendly</link>.
67  */
68 gboolean g_mem_gc_friendly = FALSE;
69 #endif
70
71 GLIB_CTOR (g_mem_init_nomessage)
72 {
73   gchar buffer[1024];
74   const gchar *val;
75   const GDebugKey keys[] = {
76     { "gc-friendly", 1 },
77   };
78   gint flags;
79
80   /* don't use g_malloc/g_message here */
81   val = _g_getenv_nomalloc ("G_DEBUG", buffer);
82   flags = !val ? 0 : g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
83   if (flags & 1)        /* gc-friendly */
84     {
85       g_mem_gc_friendly = TRUE;
86     }
87 }
88
89 /* --- malloc wrappers --- */
90 #ifndef REALLOC_0_WORKS
91 static gpointer
92 standard_realloc (gpointer mem,
93                   gsize    n_bytes)
94 {
95   if (!mem)
96     return malloc (n_bytes);
97   else
98     return realloc (mem, n_bytes);
99 }
100 #endif  /* !REALLOC_0_WORKS */
101
102 #ifdef SANE_MALLOC_PROTOS
103 #  define standard_malloc       malloc
104 #  ifdef REALLOC_0_WORKS
105 #    define standard_realloc    realloc
106 #  endif /* REALLOC_0_WORKS */
107 #  define standard_free         free
108 #  define standard_calloc       calloc
109 #  define standard_try_malloc   malloc
110 #  define standard_try_realloc  realloc
111 #else   /* !SANE_MALLOC_PROTOS */
112 static gpointer
113 standard_malloc (gsize n_bytes)
114 {
115   return malloc (n_bytes);
116 }
117 #  ifdef REALLOC_0_WORKS
118 static gpointer
119 standard_realloc (gpointer mem,
120                   gsize    n_bytes)
121 {
122   return realloc (mem, n_bytes);
123 }
124 #  endif /* REALLOC_0_WORKS */
125 static void
126 standard_free (gpointer mem)
127 {
128   free (mem);
129 }
130 static gpointer
131 standard_calloc (gsize n_blocks,
132                  gsize n_bytes)
133 {
134   return calloc (n_blocks, n_bytes);
135 }
136 #define standard_try_malloc     standard_malloc
137 #define standard_try_realloc    standard_realloc
138 #endif  /* !SANE_MALLOC_PROTOS */
139
140
141 /* --- variables --- */
142 static GMemVTable glib_mem_vtable = {
143   standard_malloc,
144   standard_realloc,
145   standard_free,
146   standard_calloc,
147   standard_try_malloc,
148   standard_try_realloc,
149 };
150
151 /**
152  * SECTION:memory
153  * @Short_Description: general memory-handling
154  * @Title: Memory Allocation
155  * 
156  * These functions provide support for allocating and freeing memory.
157  * 
158  * <note>
159  * If any call to allocate memory fails, the application is terminated.
160  * This also means that there is no need to check if the call succeeded.
161  * </note>
162  * 
163  * <note>
164  * It's important to match g_malloc() with g_free(), plain malloc() with free(),
165  * and (if you're using C++) new with delete and new[] with delete[]. Otherwise
166  * bad things can happen, since these allocators may use different memory
167  * pools (and new/delete call constructors and destructors). See also
168  * g_mem_set_vtable().
169  * </note>
170  */
171
172 /* --- functions --- */
173 /**
174  * g_malloc:
175  * @n_bytes: the number of bytes to allocate
176  * 
177  * Allocates @n_bytes bytes of memory.
178  * If @n_bytes is 0 it returns %NULL.
179  * 
180  * Returns: a pointer to the allocated memory
181  */
182 gpointer
183 g_malloc (gsize n_bytes)
184 {
185   GLIB_ENSURE_CTOR (g_mem_init_nomessage);
186
187   if (G_LIKELY (n_bytes))
188     {
189       gpointer mem;
190
191       mem = glib_mem_vtable.malloc (n_bytes);
192       TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 0, 0));
193       if (mem)
194         return mem;
195
196       g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
197                G_STRLOC, n_bytes);
198     }
199
200   TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) n_bytes, 0, 0));
201
202   return NULL;
203 }
204
205 /**
206  * g_malloc0:
207  * @n_bytes: the number of bytes to allocate
208  * 
209  * Allocates @n_bytes bytes of memory, initialized to 0's.
210  * If @n_bytes is 0 it returns %NULL.
211  * 
212  * Returns: a pointer to the allocated memory
213  */
214 gpointer
215 g_malloc0 (gsize n_bytes)
216 {
217   GLIB_ENSURE_CTOR (g_mem_init_nomessage);
218
219   if (G_LIKELY (n_bytes))
220     {
221       gpointer mem;
222
223       mem = glib_mem_vtable.calloc (1, n_bytes);
224       TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 1, 0));
225       if (mem)
226         return mem;
227
228       g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
229                G_STRLOC, n_bytes);
230     }
231
232   TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) n_bytes, 1, 0));
233
234   return NULL;
235 }
236
237 /**
238  * g_realloc:
239  * @mem: the memory to reallocate
240  * @n_bytes: new size of the memory in bytes
241  * 
242  * Reallocates the memory pointed to by @mem, so that it now has space for
243  * @n_bytes bytes of memory. It returns the new address of the memory, which may
244  * have been moved. @mem may be %NULL, in which case it's considered to
245  * have zero-length. @n_bytes may be 0, in which case %NULL will be returned
246  * and @mem will be freed unless it is %NULL.
247  * 
248  * Returns: the new address of the allocated memory
249  */
250 gpointer
251 g_realloc (gpointer mem,
252            gsize    n_bytes)
253 {
254   gpointer newmem;
255
256   GLIB_ENSURE_CTOR (g_mem_init_nomessage);
257
258   if (G_LIKELY (n_bytes))
259     {
260       newmem = glib_mem_vtable.realloc (mem, n_bytes);
261       TRACE (GLIB_MEM_REALLOC((void*) newmem, (void*)mem, (unsigned int) n_bytes, 0));
262       if (newmem)
263         return newmem;
264
265       g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
266                G_STRLOC, n_bytes);
267     }
268
269   if (mem)
270     glib_mem_vtable.free (mem);
271
272   TRACE (GLIB_MEM_REALLOC((void*) NULL, (void*)mem, 0, 0));
273
274   return NULL;
275 }
276
277 /**
278  * g_free:
279  * @mem: the memory to free
280  * 
281  * Frees the memory pointed to by @mem.
282  * If @mem is %NULL it simply returns.
283  */
284 void
285 g_free (gpointer mem)
286 {
287   GLIB_ENSURE_CTOR (g_mem_init_nomessage);
288
289   if (G_LIKELY (mem))
290     glib_mem_vtable.free (mem);
291   TRACE(GLIB_MEM_FREE((void*) mem));
292 }
293
294 /**
295  * g_try_malloc:
296  * @n_bytes: number of bytes to allocate.
297  * 
298  * Attempts to allocate @n_bytes, and returns %NULL on failure.
299  * Contrast with g_malloc(), which aborts the program on failure.
300  * 
301  * Returns: the allocated memory, or %NULL.
302  */
303 gpointer
304 g_try_malloc (gsize n_bytes)
305 {
306   gpointer mem;
307
308   GLIB_ENSURE_CTOR (g_mem_init_nomessage);
309
310   if (G_LIKELY (n_bytes))
311     mem = glib_mem_vtable.try_malloc (n_bytes);
312   else
313     mem = NULL;
314
315   TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 0, 1));
316
317   return mem;
318 }
319
320 /**
321  * g_try_malloc0:
322  * @n_bytes: number of bytes to allocate
323  * 
324  * Attempts to allocate @n_bytes, initialized to 0's, and returns %NULL on
325  * failure. Contrast with g_malloc0(), which aborts the program on failure.
326  * 
327  * Since: 2.8
328  * Returns: the allocated memory, or %NULL
329  */
330 gpointer
331 g_try_malloc0 (gsize n_bytes)
332 {
333   gpointer mem;
334
335   GLIB_ENSURE_CTOR (g_mem_init_nomessage);
336
337   if (G_LIKELY (n_bytes))
338     mem = glib_mem_vtable.try_malloc (n_bytes);
339   else
340     mem = NULL;
341
342   if (mem)
343     memset (mem, 0, n_bytes);
344
345   return mem;
346 }
347
348 /**
349  * g_try_realloc:
350  * @mem: previously-allocated memory, or %NULL.
351  * @n_bytes: number of bytes to allocate.
352  * 
353  * Attempts to realloc @mem to a new size, @n_bytes, and returns %NULL
354  * on failure. Contrast with g_realloc(), which aborts the program
355  * on failure. If @mem is %NULL, behaves the same as g_try_malloc().
356  * 
357  * Returns: the allocated memory, or %NULL.
358  */
359 gpointer
360 g_try_realloc (gpointer mem,
361                gsize    n_bytes)
362 {
363   gpointer newmem;
364
365   GLIB_ENSURE_CTOR (g_mem_init_nomessage);
366
367   if (G_LIKELY (n_bytes))
368     newmem = glib_mem_vtable.try_realloc (mem, n_bytes);
369   else
370     {
371       newmem = NULL;
372       if (mem)
373         glib_mem_vtable.free (mem);
374     }
375
376   TRACE (GLIB_MEM_REALLOC((void*) newmem, (void*)mem, (unsigned int) n_bytes, 1));
377
378   return newmem;
379 }
380
381
382 #define SIZE_OVERFLOWS(a,b) (G_UNLIKELY ((b) > 0 && (a) > G_MAXSIZE / (b)))
383
384 /**
385  * g_malloc_n:
386  * @n_blocks: the number of blocks to allocate
387  * @n_block_bytes: the size of each block in bytes
388  * 
389  * This function is similar to g_malloc(), allocating (@n_blocks * @n_block_bytes) bytes,
390  * but care is taken to detect possible overflow during multiplication.
391  * 
392  * Since: 2.24
393  * Returns: a pointer to the allocated memory
394  */
395 gpointer
396 g_malloc_n (gsize n_blocks,
397             gsize n_block_bytes)
398 {
399   if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
400     {
401       GLIB_ENSURE_CTOR (g_mem_init_nomessage);
402
403       g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
404                G_STRLOC, n_blocks, n_block_bytes);
405     }
406
407   return g_malloc (n_blocks * n_block_bytes);
408 }
409
410 /**
411  * g_malloc0_n:
412  * @n_blocks: the number of blocks to allocate
413  * @n_block_bytes: the size of each block in bytes
414  * 
415  * This function is similar to g_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes,
416  * but care is taken to detect possible overflow during multiplication.
417  * 
418  * Since: 2.24
419  * Returns: a pointer to the allocated memory
420  */
421 gpointer
422 g_malloc0_n (gsize n_blocks,
423              gsize n_block_bytes)
424 {
425   if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
426     {
427       GLIB_ENSURE_CTOR (g_mem_init_nomessage);
428
429       g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
430                G_STRLOC, n_blocks, n_block_bytes);
431     }
432
433   return g_malloc0 (n_blocks * n_block_bytes);
434 }
435
436 /**
437  * g_realloc_n:
438  * @mem: the memory to reallocate
439  * @n_blocks: the number of blocks to allocate
440  * @n_block_bytes: the size of each block in bytes
441  * 
442  * This function is similar to g_realloc(), allocating (@n_blocks * @n_block_bytes) bytes,
443  * but care is taken to detect possible overflow during multiplication.
444  * 
445  * Since: 2.24
446  * Returns: the new address of the allocated memory
447  */
448 gpointer
449 g_realloc_n (gpointer mem,
450              gsize    n_blocks,
451              gsize    n_block_bytes)
452 {
453   if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
454     {
455       GLIB_ENSURE_CTOR (g_mem_init_nomessage);
456
457       g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
458                G_STRLOC, n_blocks, n_block_bytes);
459     }
460
461   return g_realloc (mem, n_blocks * n_block_bytes);
462 }
463
464 /**
465  * g_try_malloc_n:
466  * @n_blocks: the number of blocks to allocate
467  * @n_block_bytes: the size of each block in bytes
468  * 
469  * This function is similar to g_try_malloc(), allocating (@n_blocks * @n_block_bytes) bytes,
470  * but care is taken to detect possible overflow during multiplication.
471  * 
472  * Since: 2.24
473  * Returns: the allocated memory, or %NULL.
474  */
475 gpointer
476 g_try_malloc_n (gsize n_blocks,
477                 gsize n_block_bytes)
478 {
479   if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
480     return NULL;
481
482   return g_try_malloc (n_blocks * n_block_bytes);
483 }
484
485 /**
486  * g_try_malloc0_n:
487  * @n_blocks: the number of blocks to allocate
488  * @n_block_bytes: the size of each block in bytes
489  * 
490  * This function is similar to g_try_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes,
491  * but care is taken to detect possible overflow during multiplication.
492  * 
493  * Since: 2.24
494  * Returns: the allocated memory, or %NULL
495  */
496 gpointer
497 g_try_malloc0_n (gsize n_blocks,
498                  gsize n_block_bytes)
499 {
500   if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
501     return NULL;
502
503   return g_try_malloc0 (n_blocks * n_block_bytes);
504 }
505
506 /**
507  * g_try_realloc_n:
508  * @mem: previously-allocated memory, or %NULL.
509  * @n_blocks: the number of blocks to allocate
510  * @n_block_bytes: the size of each block in bytes
511  * 
512  * This function is similar to g_try_realloc(), allocating (@n_blocks * @n_block_bytes) bytes,
513  * but care is taken to detect possible overflow during multiplication.
514  * 
515  * Since: 2.24
516  * Returns: the allocated memory, or %NULL.
517  */
518 gpointer
519 g_try_realloc_n (gpointer mem,
520                  gsize    n_blocks,
521                  gsize    n_block_bytes)
522 {
523   if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
524     return NULL;
525
526   return g_try_realloc (mem, n_blocks * n_block_bytes);
527 }
528
529
530
531 static gpointer
532 fallback_calloc (gsize n_blocks,
533                  gsize n_block_bytes)
534 {
535   gsize l = n_blocks * n_block_bytes;
536   gpointer mem = glib_mem_vtable.malloc (l);
537
538   if (mem)
539     memset (mem, 0, l);
540
541   return mem;
542 }
543
544 static gboolean vtable_set = FALSE;
545
546 /**
547  * g_mem_is_system_malloc
548  * 
549  * Checks whether the allocator used by g_malloc() is the system's
550  * malloc implementation. If it returns %TRUE memory allocated with
551  * malloc() can be used interchangeable with memory allocated using g_malloc().
552  * This function is useful for avoiding an extra copy of allocated memory returned
553  * by a non-GLib-based API.
554  *
555  * A different allocator can be set using g_mem_set_vtable().
556  *
557  * Return value: if %TRUE, malloc() and g_malloc() can be mixed.
558  **/
559 gboolean
560 g_mem_is_system_malloc (void)
561 {
562   return !vtable_set;
563 }
564
565 /**
566  * g_mem_set_vtable:
567  * @vtable: table of memory allocation routines.
568  * 
569  * Sets the #GMemVTable to use for memory allocation. You can use this to provide
570  * custom memory allocation routines. <emphasis>This function must be called
571  * before using any other GLib functions.</emphasis> The @vtable only needs to
572  * provide malloc(), realloc(), and free() functions; GLib can provide default
573  * implementations of the others. The malloc() and realloc() implementations
574  * should return %NULL on failure, GLib will handle error-checking for you.
575  * @vtable is copied, so need not persist after this function has been called.
576  */
577 void
578 g_mem_set_vtable (GMemVTable *vtable)
579 {
580   if (!vtable_set)
581     {
582       if (vtable->malloc && vtable->realloc && vtable->free)
583         {
584           glib_mem_vtable.malloc = vtable->malloc;
585           glib_mem_vtable.realloc = vtable->realloc;
586           glib_mem_vtable.free = vtable->free;
587           glib_mem_vtable.calloc = vtable->calloc ? vtable->calloc : fallback_calloc;
588           glib_mem_vtable.try_malloc = vtable->try_malloc ? vtable->try_malloc : glib_mem_vtable.malloc;
589           glib_mem_vtable.try_realloc = vtable->try_realloc ? vtable->try_realloc : glib_mem_vtable.realloc;
590           vtable_set = TRUE;
591         }
592       else
593         g_warning (G_STRLOC ": memory allocation vtable lacks one of malloc(), realloc() or free()");
594     }
595   else
596     g_warning (G_STRLOC ": memory allocation vtable can only be set once at startup");
597 }
598
599
600 /* --- memory profiling and checking --- */
601 #ifdef  G_DISABLE_CHECKS
602 /**
603  * glib_mem_profiler_table:
604  * 
605  * A #GMemVTable containing profiling variants of the memory
606  * allocation functions. Use them together with g_mem_profile()
607  * in order to get information about the memory allocation pattern
608  * of your program.
609  */
610 GMemVTable *glib_mem_profiler_table = &glib_mem_vtable;
611 void
612 g_mem_profile (void)
613 {
614 }
615 #else   /* !G_DISABLE_CHECKS */
616 typedef enum {
617   PROFILER_FREE         = 0,
618   PROFILER_ALLOC        = 1,
619   PROFILER_RELOC        = 2,
620   PROFILER_ZINIT        = 4
621 } ProfilerJob;
622 static guint *profile_data = NULL;
623 static gsize profile_allocs = 0;
624 static gsize profile_zinit = 0;
625 static gsize profile_frees = 0;
626 static GMutex gmem_profile_mutex;
627 #ifdef  G_ENABLE_DEBUG
628 static volatile gsize g_trap_free_size = 0;
629 static volatile gsize g_trap_realloc_size = 0;
630 static volatile gsize g_trap_malloc_size = 0;
631 #endif  /* G_ENABLE_DEBUG */
632
633 #define PROFILE_TABLE(f1,f2,f3)   ( ( ((f3) << 2) | ((f2) << 1) | (f1) ) * (MEM_PROFILE_TABLE_SIZE + 1))
634
635 static void
636 profiler_log (ProfilerJob job,
637               gsize       n_bytes,
638               gboolean    success)
639 {
640   g_mutex_lock (&gmem_profile_mutex);
641   if (!profile_data)
642     {
643       profile_data = standard_calloc ((MEM_PROFILE_TABLE_SIZE + 1) * 8, 
644                                       sizeof (profile_data[0]));
645       if (!profile_data)        /* memory system kiddin' me, eh? */
646         {
647           g_mutex_unlock (&gmem_profile_mutex);
648           return;
649         }
650     }
651
652   if (n_bytes < MEM_PROFILE_TABLE_SIZE)
653     profile_data[n_bytes + PROFILE_TABLE ((job & PROFILER_ALLOC) != 0,
654                                           (job & PROFILER_RELOC) != 0,
655                                           success != 0)] += 1;
656   else
657     profile_data[MEM_PROFILE_TABLE_SIZE + PROFILE_TABLE ((job & PROFILER_ALLOC) != 0,
658                                                          (job & PROFILER_RELOC) != 0,
659                                                          success != 0)] += 1;
660   if (success)
661     {
662       if (job & PROFILER_ALLOC)
663         {
664           profile_allocs += n_bytes;
665           if (job & PROFILER_ZINIT)
666             profile_zinit += n_bytes;
667         }
668       else
669         profile_frees += n_bytes;
670     }
671   g_mutex_unlock (&gmem_profile_mutex);
672 }
673
674 static void
675 profile_print_locked (guint   *local_data,
676                       gboolean success)
677 {
678   gboolean need_header = TRUE;
679   guint i;
680
681   for (i = 0; i <= MEM_PROFILE_TABLE_SIZE; i++)
682     {
683       glong t_malloc = local_data[i + PROFILE_TABLE (1, 0, success)];
684       glong t_realloc = local_data[i + PROFILE_TABLE (1, 1, success)];
685       glong t_free = local_data[i + PROFILE_TABLE (0, 0, success)];
686       glong t_refree = local_data[i + PROFILE_TABLE (0, 1, success)];
687       
688       if (!t_malloc && !t_realloc && !t_free && !t_refree)
689         continue;
690       else if (need_header)
691         {
692           need_header = FALSE;
693           g_print (" blocks of | allocated  | freed      | allocated  | freed      | n_bytes   \n");
694           g_print ("  n_bytes  | n_times by | n_times by | n_times by | n_times by | remaining \n");
695           g_print ("           | malloc()   | free()     | realloc()  | realloc()  |           \n");
696           g_print ("===========|============|============|============|============|===========\n");
697         }
698       if (i < MEM_PROFILE_TABLE_SIZE)
699         g_print ("%10u | %10ld | %10ld | %10ld | %10ld |%+11ld\n",
700                  i, t_malloc, t_free, t_realloc, t_refree,
701                  (t_malloc - t_free + t_realloc - t_refree) * i);
702       else if (i >= MEM_PROFILE_TABLE_SIZE)
703         g_print ("   >%6u | %10ld | %10ld | %10ld | %10ld |        ***\n",
704                  i, t_malloc, t_free, t_realloc, t_refree);
705     }
706   if (need_header)
707     g_print (" --- none ---\n");
708 }
709
710 /**
711  * g_mem_profile:
712  * @void:
713  * 
714  * Outputs a summary of memory usage.
715  * 
716  * It outputs the frequency of allocations of different sizes,
717  * the total number of bytes which have been allocated,
718  * the total number of bytes which have been freed,
719  * and the difference between the previous two values, i.e. the number of bytes
720  * still in use.
721  * 
722  * Note that this function will not output anything unless you have
723  * previously installed the #glib_mem_profiler_table with g_mem_set_vtable().
724  */
725
726 void
727 g_mem_profile (void)
728 {
729   guint local_data[(MEM_PROFILE_TABLE_SIZE + 1) * 8 * sizeof (profile_data[0])];
730   gsize local_allocs;
731   gsize local_zinit;
732   gsize local_frees;
733
734   GLIB_ENSURE_CTOR (g_mem_init_nomessage);
735
736   g_mutex_lock (&gmem_profile_mutex);
737
738   local_allocs = profile_allocs;
739   local_zinit = profile_zinit;
740   local_frees = profile_frees;
741
742   if (!profile_data)
743     {
744       g_mutex_unlock (&gmem_profile_mutex);
745       return;
746     }
747
748   memcpy (local_data, profile_data, 
749           (MEM_PROFILE_TABLE_SIZE + 1) * 8 * sizeof (profile_data[0]));
750   
751   g_mutex_unlock (&gmem_profile_mutex);
752
753   g_print ("GLib Memory statistics (successful operations):\n");
754   profile_print_locked (local_data, TRUE);
755   g_print ("GLib Memory statistics (failing operations):\n");
756   profile_print_locked (local_data, FALSE);
757   g_print ("Total bytes: allocated=%"G_GSIZE_FORMAT", "
758            "zero-initialized=%"G_GSIZE_FORMAT" (%.2f%%), "
759            "freed=%"G_GSIZE_FORMAT" (%.2f%%), "
760            "remaining=%"G_GSIZE_FORMAT"\n",
761            local_allocs,
762            local_zinit,
763            ((gdouble) local_zinit) / local_allocs * 100.0,
764            local_frees,
765            ((gdouble) local_frees) / local_allocs * 100.0,
766            local_allocs - local_frees);
767 }
768
769 static gpointer
770 profiler_try_malloc (gsize n_bytes)
771 {
772   gsize *p;
773
774 #ifdef  G_ENABLE_DEBUG
775   if (g_trap_malloc_size == n_bytes)
776     G_BREAKPOINT ();
777 #endif  /* G_ENABLE_DEBUG */
778
779   p = standard_malloc (sizeof (gsize) * 2 + n_bytes);
780
781   if (p)
782     {
783       p[0] = 0;         /* free count */
784       p[1] = n_bytes;   /* length */
785       profiler_log (PROFILER_ALLOC, n_bytes, TRUE);
786       p += 2;
787     }
788   else
789     profiler_log (PROFILER_ALLOC, n_bytes, FALSE);
790   
791   return p;
792 }
793
794 static gpointer
795 profiler_malloc (gsize n_bytes)
796 {
797   gpointer mem = profiler_try_malloc (n_bytes);
798
799   if (!mem)
800     g_mem_profile ();
801
802   return mem;
803 }
804
805 static gpointer
806 profiler_calloc (gsize n_blocks,
807                  gsize n_block_bytes)
808 {
809   gsize l = n_blocks * n_block_bytes;
810   gsize *p;
811
812 #ifdef  G_ENABLE_DEBUG
813   if (g_trap_malloc_size == l)
814     G_BREAKPOINT ();
815 #endif  /* G_ENABLE_DEBUG */
816   
817   p = standard_calloc (1, sizeof (gsize) * 2 + l);
818
819   if (p)
820     {
821       p[0] = 0;         /* free count */
822       p[1] = l;         /* length */
823       profiler_log (PROFILER_ALLOC | PROFILER_ZINIT, l, TRUE);
824       p += 2;
825     }
826   else
827     {
828       profiler_log (PROFILER_ALLOC | PROFILER_ZINIT, l, FALSE);
829       g_mem_profile ();
830     }
831
832   return p;
833 }
834
835 static void
836 profiler_free (gpointer mem)
837 {
838   gsize *p = mem;
839
840   p -= 2;
841   if (p[0])     /* free count */
842     {
843       g_warning ("free(%p): memory has been freed %"G_GSIZE_FORMAT" times already",
844                  p + 2, p[0]);
845       profiler_log (PROFILER_FREE,
846                     p[1],       /* length */
847                     FALSE);
848     }
849   else
850     {
851 #ifdef  G_ENABLE_DEBUG
852       if (g_trap_free_size == p[1])
853         G_BREAKPOINT ();
854 #endif  /* G_ENABLE_DEBUG */
855
856       profiler_log (PROFILER_FREE,
857                     p[1],       /* length */
858                     TRUE);
859       memset (p + 2, 0xaa, p[1]);
860
861       /* for all those that miss standard_free (p); in this place, yes,
862        * we do leak all memory when profiling, and that is intentional
863        * to catch double frees. patch submissions are futile.
864        */
865     }
866   p[0] += 1;
867 }
868
869 static gpointer
870 profiler_try_realloc (gpointer mem,
871                       gsize    n_bytes)
872 {
873   gsize *p = mem;
874
875   p -= 2;
876
877 #ifdef  G_ENABLE_DEBUG
878   if (g_trap_realloc_size == n_bytes)
879     G_BREAKPOINT ();
880 #endif  /* G_ENABLE_DEBUG */
881   
882   if (mem && p[0])      /* free count */
883     {
884       g_warning ("realloc(%p, %"G_GSIZE_FORMAT"): "
885                  "memory has been freed %"G_GSIZE_FORMAT" times already",
886                  p + 2, (gsize) n_bytes, p[0]);
887       profiler_log (PROFILER_ALLOC | PROFILER_RELOC, n_bytes, FALSE);
888
889       return NULL;
890     }
891   else
892     {
893       p = standard_realloc (mem ? p : NULL, sizeof (gsize) * 2 + n_bytes);
894
895       if (p)
896         {
897           if (mem)
898             profiler_log (PROFILER_FREE | PROFILER_RELOC, p[1], TRUE);
899           p[0] = 0;
900           p[1] = n_bytes;
901           profiler_log (PROFILER_ALLOC | PROFILER_RELOC, p[1], TRUE);
902           p += 2;
903         }
904       else
905         profiler_log (PROFILER_ALLOC | PROFILER_RELOC, n_bytes, FALSE);
906
907       return p;
908     }
909 }
910
911 static gpointer
912 profiler_realloc (gpointer mem,
913                   gsize    n_bytes)
914 {
915   mem = profiler_try_realloc (mem, n_bytes);
916
917   if (!mem)
918     g_mem_profile ();
919
920   return mem;
921 }
922
923 static GMemVTable profiler_table = {
924   profiler_malloc,
925   profiler_realloc,
926   profiler_free,
927   profiler_calloc,
928   profiler_try_malloc,
929   profiler_try_realloc,
930 };
931 GMemVTable *glib_mem_profiler_table = &profiler_table;
932
933 #endif  /* !G_DISABLE_CHECKS */