#include "config.h"
+#include "gmem.h"
+
#include <stdlib.h>
#include <string.h>
#include <signal.h>
-#include "glib.h"
-#include "gthreadprivate.h"
+#include "gbacktrace.h"
+#include "gtestutils.h"
+#include "gthread.h"
+#include "glib_trace.h"
-#include "galias.h"
#define MEM_PROFILE_TABLE_SIZE 4096
* g_mem_profile().
* REALLOC_0_WORKS is defined if g_realloc (NULL, x) works.
* SANE_MALLOC_PROTOS is defined if the systems malloc() and friends functions
- * match the corresponding GLib prototypes, keep configure.in and gmem.h in sync here.
+ * match the corresponding GLib prototypes, keep configure.ac and gmem.h in sync here.
* g_mem_gc_friendly is TRUE, freed memory should be 0-wiped.
*/
standard_try_realloc,
};
+/**
+ * SECTION:memory
+ * @Short_Description: general memory-handling
+ * @Title: Memory Allocation
+ *
+ * These functions provide support for allocating and freeing memory.
+ *
+ * <note>
+ * If any call to allocate memory fails, the application is terminated.
+ * This also means that there is no need to check if the call succeeded.
+ * </note>
+ *
+ * <note>
+ * It's important to match g_malloc() with g_free(), plain malloc() with free(),
+ * and (if you're using C++) new with delete and new[] with delete[]. Otherwise
+ * bad things can happen, since these allocators may use different memory
+ * pools (and new/delete call constructors and destructors). See also
+ * g_mem_set_vtable().
+ * </note>
+ */
/* --- functions --- */
+/**
+ * g_malloc:
+ * @n_bytes: the number of bytes to allocate
+ *
+ * Allocates @n_bytes bytes of memory.
+ * If @n_bytes is 0 it returns %NULL.
+ *
+ * Returns: a pointer to the allocated memory
+ */
gpointer
g_malloc (gsize n_bytes)
{
gpointer mem;
mem = glib_mem_vtable.malloc (n_bytes);
+ TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 0, 0));
if (mem)
return mem;
G_STRLOC, n_bytes);
}
+ TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) n_bytes, 0, 0));
+
return NULL;
}
+/**
+ * g_malloc0:
+ * @n_bytes: the number of bytes to allocate
+ *
+ * Allocates @n_bytes bytes of memory, initialized to 0's.
+ * If @n_bytes is 0 it returns %NULL.
+ *
+ * Returns: a pointer to the allocated memory
+ */
gpointer
g_malloc0 (gsize n_bytes)
{
gpointer mem;
mem = glib_mem_vtable.calloc (1, n_bytes);
+ TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 1, 0));
if (mem)
return mem;
G_STRLOC, n_bytes);
}
+ TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) n_bytes, 1, 0));
+
return NULL;
}
+/**
+ * g_realloc:
+ * @mem: the memory to reallocate
+ * @n_bytes: new size of the memory in bytes
+ *
+ * Reallocates the memory pointed to by @mem, so that it now has space for
+ * @n_bytes bytes of memory. It returns the new address of the memory, which may
+ * have been moved. @mem may be %NULL, in which case it's considered to
+ * have zero-length. @n_bytes may be 0, in which case %NULL will be returned
+ * and @mem will be freed unless it is %NULL.
+ *
+ * Returns: the new address of the allocated memory
+ */
gpointer
g_realloc (gpointer mem,
gsize n_bytes)
{
+ gpointer newmem;
+
if (G_UNLIKELY (!g_mem_initialized))
g_mem_init_nomessage();
if (G_LIKELY (n_bytes))
{
- mem = glib_mem_vtable.realloc (mem, n_bytes);
- if (mem)
- return mem;
+ newmem = glib_mem_vtable.realloc (mem, n_bytes);
+ TRACE (GLIB_MEM_REALLOC((void*) newmem, (void*)mem, (unsigned int) n_bytes, 0));
+ if (newmem)
+ return newmem;
g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
G_STRLOC, n_bytes);
if (mem)
glib_mem_vtable.free (mem);
+ TRACE (GLIB_MEM_REALLOC((void*) NULL, (void*)mem, 0, 0));
+
return NULL;
}
+/**
+ * g_free:
+ * @mem: the memory to free
+ *
+ * Frees the memory pointed to by @mem.
+ * If @mem is %NULL it simply returns.
+ */
void
g_free (gpointer mem)
{
g_mem_init_nomessage();
if (G_LIKELY (mem))
glib_mem_vtable.free (mem);
+ TRACE(GLIB_MEM_FREE((void*) mem));
}
+/**
+ * g_try_malloc:
+ * @n_bytes: number of bytes to allocate.
+ *
+ * Attempts to allocate @n_bytes, and returns %NULL on failure.
+ * Contrast with g_malloc(), which aborts the program on failure.
+ *
+ * Returns: the allocated memory, or %NULL.
+ */
gpointer
g_try_malloc (gsize n_bytes)
{
+ gpointer mem;
+
if (G_UNLIKELY (!g_mem_initialized))
g_mem_init_nomessage();
if (G_LIKELY (n_bytes))
- return glib_mem_vtable.try_malloc (n_bytes);
+ mem = glib_mem_vtable.try_malloc (n_bytes);
else
- return NULL;
+ mem = NULL;
+
+ TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 0, 1));
+
+ return mem;
}
+/**
+ * g_try_malloc0:
+ * @n_bytes: number of bytes to allocate
+ *
+ * Attempts to allocate @n_bytes, initialized to 0's, and returns %NULL on
+ * failure. Contrast with g_malloc0(), which aborts the program on failure.
+ *
+ * Since: 2.8
+ * Returns: the allocated memory, or %NULL
+ */
gpointer
g_try_malloc0 (gsize n_bytes)
{
gpointer mem;
- mem = g_try_malloc (n_bytes);
+ if (G_UNLIKELY (!g_mem_initialized))
+ g_mem_init_nomessage();
+ if (G_LIKELY (n_bytes))
+ mem = glib_mem_vtable.try_malloc (n_bytes);
+ else
+ mem = NULL;
if (mem)
memset (mem, 0, n_bytes);
return mem;
}
+/**
+ * g_try_realloc:
+ * @mem: previously-allocated memory, or %NULL.
+ * @n_bytes: number of bytes to allocate.
+ *
+ * Attempts to realloc @mem to a new size, @n_bytes, and returns %NULL
+ * on failure. Contrast with g_realloc(), which aborts the program
+ * on failure. If @mem is %NULL, behaves the same as g_try_malloc().
+ *
+ * Returns: the allocated memory, or %NULL.
+ */
gpointer
g_try_realloc (gpointer mem,
gsize n_bytes)
{
+ gpointer newmem;
+
if (G_UNLIKELY (!g_mem_initialized))
g_mem_init_nomessage();
if (G_LIKELY (n_bytes))
- return glib_mem_vtable.try_realloc (mem, n_bytes);
+ newmem = glib_mem_vtable.try_realloc (mem, n_bytes);
+ else
+ {
+ newmem = NULL;
+ if (mem)
+ glib_mem_vtable.free (mem);
+ }
- if (mem)
- glib_mem_vtable.free (mem);
+ TRACE (GLIB_MEM_REALLOC((void*) newmem, (void*)mem, (unsigned int) n_bytes, 1));
- return NULL;
+ return newmem;
}
-#define SIZE_OVERFLOWS(a,b) (G_UNLIKELY ((a) > G_MAXSIZE / (b)))
+#define SIZE_OVERFLOWS(a,b) (G_UNLIKELY ((b) > 0 && (a) > G_MAXSIZE / (b)))
+/**
+ * g_malloc_n:
+ * @n_blocks: the number of blocks to allocate
+ * @n_block_bytes: the size of each block in bytes
+ *
+ * This function is similar to g_malloc(), allocating (@n_blocks * @n_block_bytes) bytes,
+ * but care is taken to detect possible overflow during multiplication.
+ *
+ * Since: 2.24
+ * Returns: a pointer to the allocated memory
+ */
gpointer
g_malloc_n (gsize n_blocks,
gsize n_block_bytes)
return g_malloc (n_blocks * n_block_bytes);
}
+/**
+ * g_malloc0_n:
+ * @n_blocks: the number of blocks to allocate
+ * @n_block_bytes: the size of each block in bytes
+ *
+ * This function is similar to g_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes,
+ * but care is taken to detect possible overflow during multiplication.
+ *
+ * Since: 2.24
+ * Returns: a pointer to the allocated memory
+ */
gpointer
g_malloc0_n (gsize n_blocks,
gsize n_block_bytes)
return g_malloc0 (n_blocks * n_block_bytes);
}
+/**
+ * g_realloc_n:
+ * @mem: the memory to reallocate
+ * @n_blocks: the number of blocks to allocate
+ * @n_block_bytes: the size of each block in bytes
+ *
+ * This function is similar to g_realloc(), allocating (@n_blocks * @n_block_bytes) bytes,
+ * but care is taken to detect possible overflow during multiplication.
+ *
+ * Since: 2.24
+ * Returns: the new address of the allocated memory
+ */
gpointer
g_realloc_n (gpointer mem,
gsize n_blocks,
return g_realloc (mem, n_blocks * n_block_bytes);
}
+/**
+ * g_try_malloc_n:
+ * @n_blocks: the number of blocks to allocate
+ * @n_block_bytes: the size of each block in bytes
+ *
+ * This function is similar to g_try_malloc(), allocating (@n_blocks * @n_block_bytes) bytes,
+ * but care is taken to detect possible overflow during multiplication.
+ *
+ * Since: 2.24
+ * Returns: the allocated memory, or %NULL.
+ */
gpointer
g_try_malloc_n (gsize n_blocks,
gsize n_block_bytes)
return g_try_malloc (n_blocks * n_block_bytes);
}
+/**
+ * g_try_malloc0_n:
+ * @n_blocks: the number of blocks to allocate
+ * @n_block_bytes: the size of each block in bytes
+ *
+ * This function is similar to g_try_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes,
+ * but care is taken to detect possible overflow during multiplication.
+ *
+ * Since: 2.24
+ * Returns: the allocated memory, or %NULL
+ */
gpointer
g_try_malloc0_n (gsize n_blocks,
gsize n_block_bytes)
return g_try_malloc0 (n_blocks * n_block_bytes);
}
+/**
+ * g_try_realloc_n:
+ * @mem: previously-allocated memory, or %NULL.
+ * @n_blocks: the number of blocks to allocate
+ * @n_block_bytes: the size of each block in bytes
+ *
+ * This function is similar to g_try_realloc(), allocating (@n_blocks * @n_block_bytes) bytes,
+ * but care is taken to detect possible overflow during multiplication.
+ *
+ * Since: 2.24
+ * Returns: the allocated memory, or %NULL.
+ */
gpointer
g_try_realloc_n (gpointer mem,
gsize n_blocks,
*
* Checks whether the allocator used by g_malloc() is the system's
* malloc implementation. If it returns %TRUE memory allocated with
- * malloc() can be used interchangeable with memory allocated using g_malloc().
+ * malloc() can be used interchangeable with memory allocated using g_malloc().
* This function is useful for avoiding an extra copy of allocated memory returned
* by a non-GLib-based API.
*
return !vtable_set;
}
+/**
+ * g_mem_set_vtable:
+ * @vtable: table of memory allocation routines.
+ *
+ * Sets the #GMemVTable to use for memory allocation. You can use this to provide
+ * custom memory allocation routines. <emphasis>This function must be called
+ * before using any other GLib functions.</emphasis> The @vtable only needs to
+ * provide malloc(), realloc(), and free() functions; GLib can provide default
+ * implementations of the others. The malloc() and realloc() implementations
+ * should return %NULL on failure, GLib will handle error-checking for you.
+ * @vtable is copied, so need not persist after this function has been called.
+ */
void
g_mem_set_vtable (GMemVTable *vtable)
{
/* --- memory profiling and checking --- */
#ifdef G_DISABLE_CHECKS
+/**
+ * glib_mem_profiler_table:
+ *
+ * A #GMemVTable containing profiling variants of the memory
+ * allocation functions. Use them together with g_mem_profile()
+ * in order to get information about the memory allocation pattern
+ * of your program.
+ */
GMemVTable *glib_mem_profiler_table = &glib_mem_vtable;
void
g_mem_profile (void)
g_print (" --- none ---\n");
}
+/**
+ * g_mem_profile:
+ * @void:
+ *
+ * Outputs a summary of memory usage.
+ *
+ * It outputs the frequency of allocations of different sizes,
+ * the total number of bytes which have been allocated,
+ * the total number of bytes which have been freed,
+ * and the difference between the previous two values, i.e. the number of bytes
+ * still in use.
+ *
+ * Note that this function will not output anything unless you have
+ * previously installed the #glib_mem_profiler_table with g_mem_set_vtable().
+ */
+
void
g_mem_profile (void)
{
/* --- MemChunks --- */
/**
- * SECTION: allocators
+ * SECTION:allocators
* @title: Memory Allocators
* @short_description: deprecated way to allocate chunks of memory for
* GList, GSList and GNode
**/
/**
- * SECTION: memory_chunks
+ * SECTION:memory_chunks
* @title: Memory Chunks
* @short_description: deprecated way to allocate groups of equal-sized
* chunks of memory
#ifdef ENABLE_GC_FRIENDLY_DEFAULT
gboolean g_mem_gc_friendly = TRUE;
#else
+/**
+ * g_mem_gc_friendly:
+ *
+ * This variable is %TRUE if the <envar>G_DEBUG</envar> environment variable
+ * includes the key <link linkend="G_DEBUG">gc-friendly</link>.
+ */
gboolean g_mem_gc_friendly = FALSE;
#endif
gmem_profile_mutex = g_mutex_new ();
#endif
}
-
-#define __G_MEM_C__
-#include "galiasdef.c"