2022-06-29 16:02:05 +08:00
|
|
|
|
/* GLIB - Library of useful routines for C programming
|
|
|
|
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
|
|
|
|
*
|
2023-02-14 16:00:02 +08:00
|
|
|
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
|
*
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
|
|
|
|
* file for a list of people on the GLib Team. See the ChangeLog
|
|
|
|
|
* files for a list of changes. These files are distributed with
|
|
|
|
|
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* MT safe
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
|
|
#include "gmem.h"
|
|
|
|
|
|
2023-02-14 16:00:02 +08:00
|
|
|
|
#if defined(HAVE_POSIX_MEMALIGN) && !defined(_XOPEN_SOURCE)
|
|
|
|
|
# define _XOPEN_SOURCE 600
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(HAVE_MEMALIGN) || defined(HAVE__ALIGNED_MALLOC)
|
|
|
|
|
/* Required for _aligned_malloc() and _aligned_free() on Windows */
|
|
|
|
|
#include <malloc.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE__ALIGNED_MALLOC
|
|
|
|
|
/* _aligned_malloc() takes parameters of aligned_malloc() in reverse order */
|
|
|
|
|
# define aligned_alloc(alignment, size) _aligned_malloc (size, alignment)
|
|
|
|
|
|
|
|
|
|
/* _aligned_malloc()'ed memory must be freed by _align_free() on MSVC */
|
|
|
|
|
# define aligned_free(x) _aligned_free (x)
|
|
|
|
|
#else
|
|
|
|
|
# define aligned_free(x) free (x)
|
|
|
|
|
#endif
|
|
|
|
|
|
2022-06-29 16:02:05 +08:00
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
|
|
|
|
|
#include "gslice.h"
|
|
|
|
|
#include "gbacktrace.h"
|
|
|
|
|
#include "gtestutils.h"
|
|
|
|
|
#include "gthread.h"
|
|
|
|
|
#include "glib_trace.h"
|
|
|
|
|
|
|
|
|
|
/* notes on macros:
|
|
|
|
|
* having G_DISABLE_CHECKS defined disables use of glib_mem_profiler_table and
|
|
|
|
|
* g_mem_profile().
|
|
|
|
|
* If g_mem_gc_friendly is TRUE, freed memory should be 0-wiped.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* --- variables --- */
|
|
|
|
|
static GMemVTable glib_mem_vtable = {
|
|
|
|
|
malloc,
|
|
|
|
|
realloc,
|
|
|
|
|
free,
|
|
|
|
|
calloc,
|
|
|
|
|
malloc,
|
|
|
|
|
realloc,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* --- functions --- */
|
|
|
|
|
/**
|
|
|
|
|
* g_malloc:
|
|
|
|
|
* @n_bytes: the number of bytes to allocate
|
2023-02-14 16:00:02 +08:00
|
|
|
|
*
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* Allocates @n_bytes bytes of memory.
|
|
|
|
|
* If @n_bytes is 0 it returns %NULL.
|
2023-02-14 16:00:02 +08:00
|
|
|
|
*
|
|
|
|
|
* If the allocation fails (because the system is out of memory),
|
|
|
|
|
* the program is terminated.
|
|
|
|
|
*
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* Returns: a pointer to the allocated memory
|
|
|
|
|
*/
|
|
|
|
|
gpointer
|
|
|
|
|
g_malloc (gsize n_bytes)
|
|
|
|
|
{
|
|
|
|
|
if (G_LIKELY (n_bytes))
|
|
|
|
|
{
|
|
|
|
|
gpointer mem;
|
|
|
|
|
|
|
|
|
|
mem = malloc (n_bytes);
|
|
|
|
|
TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 0, 0));
|
|
|
|
|
if (mem)
|
|
|
|
|
return mem;
|
|
|
|
|
|
|
|
|
|
g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
|
|
|
|
|
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
|
2023-02-14 16:00:02 +08:00
|
|
|
|
*
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* Allocates @n_bytes bytes of memory, initialized to 0's.
|
|
|
|
|
* If @n_bytes is 0 it returns %NULL.
|
2023-02-14 16:00:02 +08:00
|
|
|
|
*
|
|
|
|
|
* If the allocation fails (because the system is out of memory),
|
|
|
|
|
* the program is terminated.
|
|
|
|
|
*
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* Returns: a pointer to the allocated memory
|
|
|
|
|
*/
|
|
|
|
|
gpointer
|
|
|
|
|
g_malloc0 (gsize n_bytes)
|
|
|
|
|
{
|
|
|
|
|
if (G_LIKELY (n_bytes))
|
|
|
|
|
{
|
|
|
|
|
gpointer mem;
|
|
|
|
|
|
|
|
|
|
mem = calloc (1, n_bytes);
|
|
|
|
|
TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 1, 0));
|
|
|
|
|
if (mem)
|
|
|
|
|
return mem;
|
|
|
|
|
|
|
|
|
|
g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
|
|
|
|
|
G_STRLOC, n_bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) n_bytes, 1, 0));
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_realloc:
|
|
|
|
|
* @mem: (nullable): the memory to reallocate
|
|
|
|
|
* @n_bytes: new size of the memory in bytes
|
2023-02-14 16:00:02 +08:00
|
|
|
|
*
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* 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.
|
2023-02-14 16:00:02 +08:00
|
|
|
|
*
|
|
|
|
|
* If the allocation fails (because the system is out of memory),
|
|
|
|
|
* the program is terminated.
|
|
|
|
|
*
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* Returns: the new address of the allocated memory
|
|
|
|
|
*/
|
|
|
|
|
gpointer
|
|
|
|
|
g_realloc (gpointer mem,
|
|
|
|
|
gsize n_bytes)
|
|
|
|
|
{
|
|
|
|
|
gpointer newmem;
|
|
|
|
|
|
|
|
|
|
if (G_LIKELY (n_bytes))
|
|
|
|
|
{
|
|
|
|
|
newmem = 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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free (mem);
|
|
|
|
|
|
|
|
|
|
TRACE (GLIB_MEM_REALLOC((void*) NULL, (void*)mem, 0, 0));
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_free:
|
|
|
|
|
* @mem: (nullable): the memory to free
|
|
|
|
|
*
|
|
|
|
|
* Frees the memory pointed to by @mem.
|
|
|
|
|
*
|
2024-02-29 14:32:35 +08:00
|
|
|
|
* If you know the allocated size of @mem, calling g_free_sized() may be faster,
|
|
|
|
|
* depending on the libc implementation in use.
|
|
|
|
|
*
|
|
|
|
|
* Starting from GLib 2.78, this may happen automatically in case a GCC
|
|
|
|
|
* compatible compiler is used with some optimization level and the allocated
|
|
|
|
|
* size is known at compile time (see [documentation of
|
|
|
|
|
* `__builtin_object_size()`](https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html)
|
|
|
|
|
* to understand its caveats).
|
|
|
|
|
*
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* If @mem is %NULL it simply returns, so there is no need to check @mem
|
|
|
|
|
* against %NULL before calling this function.
|
|
|
|
|
*/
|
|
|
|
|
void
|
2024-02-29 14:32:35 +08:00
|
|
|
|
(g_free) (gpointer mem)
|
2022-06-29 16:02:05 +08:00
|
|
|
|
{
|
|
|
|
|
free (mem);
|
|
|
|
|
TRACE(GLIB_MEM_FREE((void*) mem));
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-29 14:32:35 +08:00
|
|
|
|
/**
|
|
|
|
|
* g_free_sized:
|
|
|
|
|
* @mem: (nullable): the memory to free
|
|
|
|
|
* @size: size of @mem, in bytes
|
|
|
|
|
*
|
|
|
|
|
* Frees the memory pointed to by @mem, assuming it is has the given @size.
|
|
|
|
|
*
|
|
|
|
|
* If @mem is %NULL this is a no-op (and @size is ignored).
|
|
|
|
|
*
|
|
|
|
|
* It is an error if @size doesn’t match the size passed when @mem was
|
|
|
|
|
* allocated. @size is passed to this function to allow optimizations in the
|
|
|
|
|
* allocator. If you don’t know the allocation size, use g_free() instead.
|
|
|
|
|
*
|
|
|
|
|
* In case a GCC compatible compiler is used, this function may be used
|
|
|
|
|
* automatically via g_free() if the allocated size is known at compile time,
|
|
|
|
|
* since GLib 2.78.
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.76
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
g_free_sized (void *mem,
|
|
|
|
|
size_t size)
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_FREE_SIZED
|
|
|
|
|
free_sized (mem, size);
|
|
|
|
|
#else
|
|
|
|
|
free (mem);
|
|
|
|
|
#endif
|
|
|
|
|
TRACE (GLIB_MEM_FREE ((void*) mem));
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-29 16:02:05 +08:00
|
|
|
|
/**
|
|
|
|
|
* g_clear_pointer: (skip)
|
2024-02-29 14:32:35 +08:00
|
|
|
|
* @pp: (nullable) (not optional) (inout) (transfer full): a pointer to a
|
|
|
|
|
* variable, struct member etc. holding a pointer
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* @destroy: a function to which a gpointer can be passed, to destroy *@pp
|
|
|
|
|
*
|
|
|
|
|
* Clears a reference to a variable.
|
|
|
|
|
*
|
|
|
|
|
* @pp must not be %NULL.
|
|
|
|
|
*
|
|
|
|
|
* If the reference is %NULL then this function does nothing.
|
|
|
|
|
* Otherwise, the variable is destroyed using @destroy and the
|
|
|
|
|
* pointer is set to %NULL.
|
|
|
|
|
*
|
|
|
|
|
* A macro is also included that allows this function to be used without
|
|
|
|
|
* pointer casts. This will mask any warnings about incompatible function types
|
|
|
|
|
* or calling conventions, so you must ensure that your @destroy function is
|
|
|
|
|
* compatible with being called as `GDestroyNotify` using the standard calling
|
|
|
|
|
* convention for the platform that GLib was compiled for; otherwise the program
|
|
|
|
|
* will experience undefined behaviour.
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.34
|
|
|
|
|
**/
|
|
|
|
|
#undef g_clear_pointer
|
|
|
|
|
void
|
|
|
|
|
g_clear_pointer (gpointer *pp,
|
|
|
|
|
GDestroyNotify destroy)
|
|
|
|
|
{
|
|
|
|
|
gpointer _p;
|
|
|
|
|
|
|
|
|
|
_p = *pp;
|
|
|
|
|
if (_p)
|
|
|
|
|
{
|
|
|
|
|
*pp = NULL;
|
|
|
|
|
destroy (_p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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_LIKELY (n_bytes))
|
|
|
|
|
mem = malloc (n_bytes);
|
|
|
|
|
else
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
if (G_LIKELY (n_bytes))
|
|
|
|
|
mem = calloc (1, n_bytes);
|
|
|
|
|
else
|
|
|
|
|
mem = NULL;
|
|
|
|
|
|
|
|
|
|
return mem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_try_realloc:
|
|
|
|
|
* @mem: (nullable): 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_LIKELY (n_bytes))
|
|
|
|
|
newmem = realloc (mem, n_bytes);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
newmem = NULL;
|
|
|
|
|
free (mem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TRACE (GLIB_MEM_REALLOC((void*) newmem, (void*)mem, (unsigned int) n_bytes, 1));
|
|
|
|
|
|
|
|
|
|
return newmem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#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
|
2023-02-14 16:00:02 +08:00
|
|
|
|
*
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* This function is similar to g_malloc(), allocating (@n_blocks * @n_block_bytes) bytes,
|
|
|
|
|
* but care is taken to detect possible overflow during multiplication.
|
2023-02-14 16:00:02 +08:00
|
|
|
|
*
|
|
|
|
|
* If the allocation fails (because the system is out of memory),
|
|
|
|
|
* the program is terminated.
|
|
|
|
|
*
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* Since: 2.24
|
|
|
|
|
* Returns: a pointer to the allocated memory
|
|
|
|
|
*/
|
|
|
|
|
gpointer
|
|
|
|
|
g_malloc_n (gsize n_blocks,
|
|
|
|
|
gsize n_block_bytes)
|
|
|
|
|
{
|
|
|
|
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
|
|
|
|
|
{
|
|
|
|
|
g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
|
|
|
|
|
G_STRLOC, n_blocks, 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
|
2023-02-14 16:00:02 +08:00
|
|
|
|
*
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* This function is similar to g_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes,
|
|
|
|
|
* but care is taken to detect possible overflow during multiplication.
|
2023-02-14 16:00:02 +08:00
|
|
|
|
*
|
|
|
|
|
* If the allocation fails (because the system is out of memory),
|
|
|
|
|
* the program is terminated.
|
|
|
|
|
*
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* Since: 2.24
|
|
|
|
|
* Returns: a pointer to the allocated memory
|
|
|
|
|
*/
|
|
|
|
|
gpointer
|
|
|
|
|
g_malloc0_n (gsize n_blocks,
|
|
|
|
|
gsize n_block_bytes)
|
|
|
|
|
{
|
|
|
|
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
|
|
|
|
|
{
|
|
|
|
|
g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
|
|
|
|
|
G_STRLOC, n_blocks, n_block_bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return g_malloc0 (n_blocks * n_block_bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_realloc_n:
|
|
|
|
|
* @mem: (nullable): the memory to reallocate
|
|
|
|
|
* @n_blocks: the number of blocks to allocate
|
|
|
|
|
* @n_block_bytes: the size of each block in bytes
|
2023-02-14 16:00:02 +08:00
|
|
|
|
*
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* This function is similar to g_realloc(), allocating (@n_blocks * @n_block_bytes) bytes,
|
|
|
|
|
* but care is taken to detect possible overflow during multiplication.
|
2023-02-14 16:00:02 +08:00
|
|
|
|
*
|
|
|
|
|
* If the allocation fails (because the system is out of memory),
|
|
|
|
|
* the program is terminated.
|
|
|
|
|
*
|
2022-06-29 16:02:05 +08:00
|
|
|
|
* Since: 2.24
|
|
|
|
|
* Returns: the new address of the allocated memory
|
|
|
|
|
*/
|
|
|
|
|
gpointer
|
|
|
|
|
g_realloc_n (gpointer mem,
|
|
|
|
|
gsize n_blocks,
|
|
|
|
|
gsize n_block_bytes)
|
|
|
|
|
{
|
|
|
|
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
|
|
|
|
|
{
|
|
|
|
|
g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
|
|
|
|
|
G_STRLOC, n_blocks, n_block_bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return g_try_malloc0 (n_blocks * n_block_bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_try_realloc_n:
|
|
|
|
|
* @mem: (nullable): 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,
|
|
|
|
|
gsize n_block_bytes)
|
|
|
|
|
{
|
|
|
|
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return g_try_realloc (mem, n_blocks * n_block_bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_mem_is_system_malloc:
|
|
|
|
|
*
|
|
|
|
|
* 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 interchangeably 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.
|
|
|
|
|
*
|
|
|
|
|
* Returns: if %TRUE, malloc() and g_malloc() can be mixed.
|
|
|
|
|
*
|
|
|
|
|
* Deprecated: 2.46: GLib always uses the system malloc, so this function always
|
|
|
|
|
* returns %TRUE.
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
g_mem_is_system_malloc (void)
|
|
|
|
|
{
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_mem_set_vtable:
|
|
|
|
|
* @vtable: table of memory allocation routines.
|
|
|
|
|
*
|
|
|
|
|
* This function used to let you override the memory allocation function.
|
|
|
|
|
* However, its use was incompatible with the use of global constructors
|
|
|
|
|
* in GLib and GIO, because those use the GLib allocators before main is
|
|
|
|
|
* reached. Therefore this function is now deprecated and is just a stub.
|
|
|
|
|
*
|
|
|
|
|
* Deprecated: 2.46: This function now does nothing. Use other memory
|
|
|
|
|
* profiling tools instead
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
g_mem_set_vtable (GMemVTable *vtable)
|
|
|
|
|
{
|
|
|
|
|
g_warning (G_STRLOC ": custom memory allocation vtable not supported");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* glib_mem_profiler_table:
|
|
|
|
|
*
|
|
|
|
|
* Used to be a #GMemVTable containing profiling variants of the memory
|
|
|
|
|
* allocation functions, but this variable shouldn't be modified anymore.
|
|
|
|
|
*
|
|
|
|
|
* Deprecated: 2.46: Use other memory profiling tools instead
|
|
|
|
|
*/
|
|
|
|
|
GMemVTable *glib_mem_profiler_table = &glib_mem_vtable;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_mem_profile:
|
|
|
|
|
*
|
|
|
|
|
* GLib used to support some tools for memory profiling, but this
|
|
|
|
|
* no longer works. There are many other useful tools for memory
|
|
|
|
|
* profiling these days which can be used instead.
|
|
|
|
|
*
|
|
|
|
|
* Deprecated: 2.46: Use other memory profiling tools instead
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
g_mem_profile (void)
|
|
|
|
|
{
|
|
|
|
|
g_warning (G_STRLOC ": memory profiling not supported");
|
|
|
|
|
}
|
2023-02-14 16:00:02 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_aligned_alloc:
|
|
|
|
|
* @n_blocks: the number of blocks to allocate
|
|
|
|
|
* @n_block_bytes: the size of each block in bytes
|
|
|
|
|
* @alignment: the alignment to be enforced, which must be a positive power of 2
|
|
|
|
|
* and a multiple of `sizeof(void*)`
|
|
|
|
|
*
|
|
|
|
|
* This function is similar to g_malloc(), allocating (@n_blocks * @n_block_bytes)
|
|
|
|
|
* bytes, but care is taken to align the allocated memory to with the given
|
|
|
|
|
* alignment value. Additionally, it will detect possible overflow during
|
|
|
|
|
* multiplication.
|
|
|
|
|
*
|
|
|
|
|
* If the allocation fails (because the system is out of memory),
|
|
|
|
|
* the program is terminated.
|
|
|
|
|
*
|
|
|
|
|
* Aligned memory allocations returned by this function can only be
|
2024-02-29 14:32:35 +08:00
|
|
|
|
* freed using g_aligned_free_sized() or g_aligned_free().
|
2023-02-14 16:00:02 +08:00
|
|
|
|
*
|
|
|
|
|
* Returns: (transfer full): the allocated memory
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.72
|
|
|
|
|
*/
|
|
|
|
|
gpointer
|
|
|
|
|
g_aligned_alloc (gsize n_blocks,
|
|
|
|
|
gsize n_block_bytes,
|
|
|
|
|
gsize alignment)
|
|
|
|
|
{
|
|
|
|
|
gpointer res = NULL;
|
|
|
|
|
gsize real_size;
|
|
|
|
|
|
|
|
|
|
if (G_UNLIKELY ((alignment == 0) || (alignment & (alignment - 1)) != 0))
|
|
|
|
|
{
|
|
|
|
|
g_error ("%s: alignment %"G_GSIZE_FORMAT" must be a positive power of two",
|
|
|
|
|
G_STRLOC, alignment);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (G_UNLIKELY ((alignment % sizeof (void *)) != 0))
|
|
|
|
|
{
|
|
|
|
|
g_error ("%s: alignment %"G_GSIZE_FORMAT" must be a multiple of %"G_GSIZE_FORMAT,
|
|
|
|
|
G_STRLOC, alignment, sizeof (void *));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
|
|
|
|
|
{
|
|
|
|
|
g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
|
|
|
|
|
G_STRLOC, n_blocks, n_block_bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
real_size = n_blocks * n_block_bytes;
|
|
|
|
|
|
|
|
|
|
if (G_UNLIKELY (real_size == 0))
|
|
|
|
|
{
|
|
|
|
|
TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) real_size, 0, 0));
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We need to clear errno because posix_memalign() will use its return
|
|
|
|
|
* value in the same way memalign() and aligned_alloc() will set errno.
|
|
|
|
|
* Additionally, posix_memalign() will warn if its return value is left
|
|
|
|
|
* unassigned.
|
|
|
|
|
*
|
|
|
|
|
* We handle all possible return values (ENOMEM and EINVAL) with either
|
|
|
|
|
* precondition or postcondition checking.
|
|
|
|
|
*/
|
|
|
|
|
errno = 0;
|
|
|
|
|
|
|
|
|
|
#if defined(HAVE_POSIX_MEMALIGN)
|
|
|
|
|
errno = posix_memalign (&res, alignment, real_size);
|
|
|
|
|
#elif defined(HAVE_ALIGNED_ALLOC) || defined(HAVE__ALIGNED_MALLOC)
|
|
|
|
|
/* real_size must be a multiple of alignment */
|
|
|
|
|
if (real_size % alignment != 0)
|
|
|
|
|
{
|
|
|
|
|
gsize offset = real_size % alignment;
|
|
|
|
|
|
|
|
|
|
if (G_MAXSIZE - real_size < (alignment - offset))
|
|
|
|
|
{
|
|
|
|
|
g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"+%"G_GSIZE_FORMAT" bytes",
|
|
|
|
|
G_STRLOC, real_size, (alignment - offset));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
real_size += (alignment - offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res = aligned_alloc (alignment, real_size);
|
|
|
|
|
#elif defined(HAVE_MEMALIGN)
|
|
|
|
|
res = memalign (alignment, real_size);
|
|
|
|
|
#else
|
|
|
|
|
# error "This platform does not have an aligned memory allocator."
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
TRACE (GLIB_MEM_ALLOC((void*) res, (unsigned int) real_size, 0, 0));
|
|
|
|
|
if (res)
|
|
|
|
|
return res;
|
|
|
|
|
|
|
|
|
|
g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
|
|
|
|
|
G_STRLOC, real_size);
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_aligned_alloc0:
|
|
|
|
|
* @n_blocks: the number of blocks to allocate
|
|
|
|
|
* @n_block_bytes: the size of each block in bytes
|
|
|
|
|
* @alignment: the alignment to be enforced, which must be a positive power of 2
|
|
|
|
|
* and a multiple of `sizeof(void*)`
|
|
|
|
|
*
|
|
|
|
|
* This function is similar to g_aligned_alloc(), but it will
|
|
|
|
|
* also clear the allocated memory before returning it.
|
|
|
|
|
*
|
|
|
|
|
* Returns: (transfer full): the allocated, cleared memory
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.72
|
|
|
|
|
*/
|
|
|
|
|
gpointer
|
|
|
|
|
g_aligned_alloc0 (gsize n_blocks,
|
|
|
|
|
gsize n_block_bytes,
|
|
|
|
|
gsize alignment)
|
|
|
|
|
{
|
|
|
|
|
gpointer res = g_aligned_alloc (n_blocks, n_block_bytes, alignment);
|
|
|
|
|
|
|
|
|
|
if (G_LIKELY (res != NULL))
|
|
|
|
|
memset (res, 0, n_blocks * n_block_bytes);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_aligned_free:
|
|
|
|
|
* @mem: (nullable): the memory to deallocate
|
|
|
|
|
*
|
|
|
|
|
* Frees the memory allocated by g_aligned_alloc().
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.72
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
g_aligned_free (gpointer mem)
|
|
|
|
|
{
|
|
|
|
|
aligned_free (mem);
|
|
|
|
|
}
|
2024-02-29 14:32:35 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_aligned_free_sized:
|
|
|
|
|
* @mem: (nullable): the memory to free
|
|
|
|
|
* @alignment: alignment of @mem
|
|
|
|
|
* @size: size of @mem, in bytes
|
|
|
|
|
*
|
|
|
|
|
* Frees the memory pointed to by @mem, assuming it is has the given @size and
|
|
|
|
|
* @alignment.
|
|
|
|
|
*
|
|
|
|
|
* If @mem is %NULL this is a no-op (and @size is ignored).
|
|
|
|
|
*
|
|
|
|
|
* It is an error if @size doesn’t match the size, or @alignment doesn’t match
|
|
|
|
|
* the alignment, passed when @mem was allocated. @size and @alignment are
|
|
|
|
|
* passed to this function to allow optimizations in the allocator. If you
|
|
|
|
|
* don’t know either of them, use g_aligned_free() instead.
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.76
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
g_aligned_free_sized (void *mem,
|
|
|
|
|
size_t alignment,
|
|
|
|
|
size_t size)
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_FREE_ALIGNED_SIZED
|
|
|
|
|
free_aligned_sized (mem, alignment, size);
|
|
|
|
|
#else
|
|
|
|
|
aligned_free (mem);
|
|
|
|
|
#endif
|
|
|
|
|
}
|