| /* GLIB - Library of useful routines for C programming |
| * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
| * |
| * SPDX-License-Identifier: LGPL-2.1-or-later |
| * |
| * 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" |
| |
| #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 |
| |
| #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 |
| * |
| * Allocates @n_bytes bytes of memory. |
| * If @n_bytes is 0 it returns %NULL. |
| * |
| * If the allocation fails (because the system is out of memory), |
| * the program is terminated. |
| * |
| * 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 |
| * |
| * Allocates @n_bytes bytes of memory, initialized to 0's. |
| * If @n_bytes is 0 it returns %NULL. |
| * |
| * If the allocation fails (because the system is out of memory), |
| * the program is terminated. |
| * |
| * 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 |
| * |
| * 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. |
| * |
| * If the allocation fails (because the system is out of memory), |
| * the program is terminated. |
| * |
| * 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. |
| * |
| * 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). |
| * |
| * If @mem is %NULL it simply returns, so there is no need to check @mem |
| * against %NULL before calling this function. |
| */ |
| void |
| (g_free) (gpointer mem) |
| { |
| free (mem); |
| TRACE(GLIB_MEM_FREE((void*) mem)); |
| } |
| |
| /** |
| * 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)); |
| } |
| |
| /** |
| * g_clear_pointer: (skip) |
| * @pp: (nullable) (not optional) (inout) (transfer full): a pointer to a |
| * variable, struct member etc. holding a pointer |
| * @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 |
| * |
| * This function is similar to g_malloc(), allocating (@n_blocks * @n_block_bytes) bytes, |
| * but care is taken to detect possible overflow during multiplication. |
| * |
| * If the allocation fails (because the system is out of memory), |
| * the program is terminated. |
| * |
| * 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 |
| * |
| * This function is similar to g_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes, |
| * but care is taken to detect possible overflow during multiplication. |
| * |
| * If the allocation fails (because the system is out of memory), |
| * the program is terminated. |
| * |
| * 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 |
| * |
| * This function is similar to g_realloc(), allocating (@n_blocks * @n_block_bytes) bytes, |
| * but care is taken to detect possible overflow during multiplication. |
| * |
| * If the allocation fails (because the system is out of memory), |
| * the program is terminated. |
| * |
| * 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"); |
| } |
| |
| /** |
| * 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 |
| * freed using g_aligned_free_sized() or g_aligned_free(). |
| * |
| * 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); |
| } |
| |
| /** |
| * 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 |
| } |