(root)/
glib-2.79.0/
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   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   *
       6   * This library is free software; you can redistribute it and/or
       7   * modify it under the terms of the GNU Lesser General Public
       8   * License as published by the Free Software Foundation; either
       9   * version 2.1 of the License, or (at your option) any later version.
      10   *
      11   * This library is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14   * Lesser General Public License for more details.
      15   *
      16   * You should have received a copy of the GNU Lesser General Public
      17   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      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  #if defined(HAVE_POSIX_MEMALIGN) && !defined(_XOPEN_SOURCE)
      36  # define _XOPEN_SOURCE 600
      37  #endif
      38  
      39  #if defined(HAVE_MEMALIGN) || defined(HAVE__ALIGNED_MALLOC)
      40  /* Required for _aligned_malloc() and _aligned_free() on Windows */
      41  #include <malloc.h>
      42  #endif
      43  
      44  #ifdef HAVE__ALIGNED_MALLOC
      45  /* _aligned_malloc() takes parameters of aligned_malloc() in reverse order */
      46  # define aligned_alloc(alignment, size) _aligned_malloc (size, alignment)
      47  
      48  /* _aligned_malloc()'ed memory must be freed by _align_free() on MSVC */
      49  # define aligned_free(x) _aligned_free (x)
      50  #else
      51  # define aligned_free(x) free (x)
      52  #endif
      53  
      54  #include <stdlib.h>
      55  #include <string.h>
      56  #include <signal.h>
      57  
      58  #include "gslice.h"
      59  #include "gbacktrace.h"
      60  #include "gtestutils.h"
      61  #include "gthread.h"
      62  #include "glib_trace.h"
      63  
      64  /* notes on macros:
      65   * having G_DISABLE_CHECKS defined disables use of glib_mem_profiler_table and
      66   * g_mem_profile().
      67   * If g_mem_gc_friendly is TRUE, freed memory should be 0-wiped.
      68   */
      69  
      70  /* --- variables --- */
      71  static GMemVTable glib_mem_vtable = {
      72    malloc,
      73    realloc,
      74    free,
      75    calloc,
      76    malloc,
      77    realloc,
      78  };
      79  
      80  /* --- functions --- */
      81  /**
      82   * g_malloc:
      83   * @n_bytes: the number of bytes to allocate
      84   *
      85   * Allocates @n_bytes bytes of memory.
      86   * If @n_bytes is 0 it returns %NULL.
      87   *
      88   * If the allocation fails (because the system is out of memory),
      89   * the program is terminated.
      90   *
      91   * Returns: a pointer to the allocated memory
      92   */
      93  gpointer
      94  g_malloc (gsize n_bytes)
      95  {
      96    if (G_LIKELY (n_bytes))
      97      {
      98        gpointer mem;
      99  
     100        mem = malloc (n_bytes);
     101        TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 0, 0));
     102        if (mem)
     103  	return mem;
     104  
     105        g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
     106                 G_STRLOC, n_bytes);
     107      }
     108  
     109    TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) n_bytes, 0, 0));
     110  
     111    return NULL;
     112  }
     113  
     114  /**
     115   * g_malloc0:
     116   * @n_bytes: the number of bytes to allocate
     117   *
     118   * Allocates @n_bytes bytes of memory, initialized to 0's.
     119   * If @n_bytes is 0 it returns %NULL.
     120   *
     121   * If the allocation fails (because the system is out of memory),
     122   * the program is terminated.
     123   *
     124   * Returns: a pointer to the allocated memory
     125   */
     126  gpointer
     127  g_malloc0 (gsize n_bytes)
     128  {
     129    if (G_LIKELY (n_bytes))
     130      {
     131        gpointer mem;
     132  
     133        mem = calloc (1, n_bytes);
     134        TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 1, 0));
     135        if (mem)
     136  	return mem;
     137  
     138        g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
     139                 G_STRLOC, n_bytes);
     140      }
     141  
     142    TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) n_bytes, 1, 0));
     143  
     144    return NULL;
     145  }
     146  
     147  /**
     148   * g_realloc:
     149   * @mem: (nullable): the memory to reallocate
     150   * @n_bytes: new size of the memory in bytes
     151   *
     152   * Reallocates the memory pointed to by @mem, so that it now has space for
     153   * @n_bytes bytes of memory. It returns the new address of the memory, which may
     154   * have been moved. @mem may be %NULL, in which case it's considered to
     155   * have zero-length. @n_bytes may be 0, in which case %NULL will be returned
     156   * and @mem will be freed unless it is %NULL.
     157   *
     158   * If the allocation fails (because the system is out of memory),
     159   * the program is terminated.
     160   *
     161   * Returns: the new address of the allocated memory
     162   */
     163  gpointer
     164  g_realloc (gpointer mem,
     165  	   gsize    n_bytes)
     166  {
     167    gpointer newmem;
     168  
     169    if (G_LIKELY (n_bytes))
     170      {
     171        newmem = realloc (mem, n_bytes);
     172        TRACE (GLIB_MEM_REALLOC((void*) newmem, (void*)mem, (unsigned int) n_bytes, 0));
     173        if (newmem)
     174  	return newmem;
     175  
     176        g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
     177                 G_STRLOC, n_bytes);
     178      }
     179  
     180    free (mem);
     181  
     182    TRACE (GLIB_MEM_REALLOC((void*) NULL, (void*)mem, 0, 0));
     183  
     184    return NULL;
     185  }
     186  
     187  /**
     188   * g_free:
     189   * @mem: (nullable): the memory to free
     190   * 
     191   * Frees the memory pointed to by @mem.
     192   *
     193   * If you know the allocated size of @mem, calling g_free_sized() may be faster,
     194   * depending on the libc implementation in use.
     195   *
     196   * Starting from GLib 2.78, this may happen automatically in case a GCC
     197   * compatible compiler is used with some optimization level and the allocated
     198   * size is known at compile time (see [documentation of
     199   * `__builtin_object_size()`](https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html)
     200   * to understand its caveats).
     201   *
     202   * If @mem is %NULL it simply returns, so there is no need to check @mem
     203   * against %NULL before calling this function.
     204   */
     205  void
     206  (g_free) (gpointer mem)
     207  {
     208    free (mem);
     209    TRACE(GLIB_MEM_FREE((void*) mem));
     210  }
     211  
     212  /**
     213   * g_free_sized:
     214   * @mem: (nullable): the memory to free
     215   * @size: size of @mem, in bytes
     216   *
     217   * Frees the memory pointed to by @mem, assuming it is has the given @size.
     218   *
     219   * If @mem is %NULL this is a no-op (and @size is ignored).
     220   *
     221   * It is an error if @size doesn’t match the size passed when @mem was
     222   * allocated. @size is passed to this function to allow optimizations in the
     223   * allocator. If you don’t know the allocation size, use g_free() instead.
     224   *
     225   * In case a GCC compatible compiler is used, this function may be used
     226   * automatically via g_free() if the allocated size is known at compile time,
     227   * since GLib 2.78.
     228   *
     229   * Since: 2.76
     230   */
     231  void
     232  g_free_sized (void   *mem,
     233                size_t  size)
     234  {
     235  #ifdef HAVE_FREE_SIZED
     236    free_sized (mem, size);
     237  #else
     238    free (mem);
     239  #endif
     240    TRACE (GLIB_MEM_FREE ((void*) mem));
     241  }
     242  
     243  /**
     244   * g_clear_pointer: (skip)
     245   * @pp: (nullable) (not optional) (inout) (transfer full): a pointer to a
     246   *   variable, struct member etc. holding a pointer
     247   * @destroy: a function to which a gpointer can be passed, to destroy *@pp
     248   *
     249   * Clears a reference to a variable.
     250   *
     251   * @pp must not be %NULL.
     252   *
     253   * If the reference is %NULL then this function does nothing.
     254   * Otherwise, the variable is destroyed using @destroy and the
     255   * pointer is set to %NULL.
     256   *
     257   * A macro is also included that allows this function to be used without
     258   * pointer casts. This will mask any warnings about incompatible function types
     259   * or calling conventions, so you must ensure that your @destroy function is
     260   * compatible with being called as `GDestroyNotify` using the standard calling
     261   * convention for the platform that GLib was compiled for; otherwise the program
     262   * will experience undefined behaviour.
     263   *
     264   * Since: 2.34
     265   **/
     266  #undef g_clear_pointer
     267  void
     268  g_clear_pointer (gpointer      *pp,
     269                   GDestroyNotify destroy)
     270  {
     271    gpointer _p;
     272  
     273    _p = *pp;
     274    if (_p)
     275      {
     276        *pp = NULL;
     277        destroy (_p);
     278      }
     279  }
     280  
     281  /**
     282   * g_try_malloc:
     283   * @n_bytes: number of bytes to allocate.
     284   * 
     285   * Attempts to allocate @n_bytes, and returns %NULL on failure.
     286   * Contrast with g_malloc(), which aborts the program on failure.
     287   * 
     288   * Returns: the allocated memory, or %NULL.
     289   */
     290  gpointer
     291  g_try_malloc (gsize n_bytes)
     292  {
     293    gpointer mem;
     294  
     295    if (G_LIKELY (n_bytes))
     296      mem = malloc (n_bytes);
     297    else
     298      mem = NULL;
     299  
     300    TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 0, 1));
     301  
     302    return mem;
     303  }
     304  
     305  /**
     306   * g_try_malloc0:
     307   * @n_bytes: number of bytes to allocate
     308   * 
     309   * Attempts to allocate @n_bytes, initialized to 0's, and returns %NULL on
     310   * failure. Contrast with g_malloc0(), which aborts the program on failure.
     311   * 
     312   * Since: 2.8
     313   * Returns: the allocated memory, or %NULL
     314   */
     315  gpointer
     316  g_try_malloc0 (gsize n_bytes)
     317  {
     318    gpointer mem;
     319  
     320    if (G_LIKELY (n_bytes))
     321      mem = calloc (1, n_bytes);
     322    else
     323      mem = NULL;
     324  
     325    return mem;
     326  }
     327  
     328  /**
     329   * g_try_realloc:
     330   * @mem: (nullable): previously-allocated memory, or %NULL.
     331   * @n_bytes: number of bytes to allocate.
     332   * 
     333   * Attempts to realloc @mem to a new size, @n_bytes, and returns %NULL
     334   * on failure. Contrast with g_realloc(), which aborts the program
     335   * on failure.
     336   *
     337   * If @mem is %NULL, behaves the same as g_try_malloc().
     338   * 
     339   * Returns: the allocated memory, or %NULL.
     340   */
     341  gpointer
     342  g_try_realloc (gpointer mem,
     343  	       gsize    n_bytes)
     344  {
     345    gpointer newmem;
     346  
     347    if (G_LIKELY (n_bytes))
     348      newmem = realloc (mem, n_bytes);
     349    else
     350      {
     351        newmem = NULL;
     352        free (mem);
     353      }
     354  
     355    TRACE (GLIB_MEM_REALLOC((void*) newmem, (void*)mem, (unsigned int) n_bytes, 1));
     356  
     357    return newmem;
     358  }
     359  
     360  
     361  #define SIZE_OVERFLOWS(a,b) (G_UNLIKELY ((b) > 0 && (a) > G_MAXSIZE / (b)))
     362  
     363  /**
     364   * g_malloc_n:
     365   * @n_blocks: the number of blocks to allocate
     366   * @n_block_bytes: the size of each block in bytes
     367   *
     368   * This function is similar to g_malloc(), allocating (@n_blocks * @n_block_bytes) bytes,
     369   * but care is taken to detect possible overflow during multiplication.
     370   *
     371   * If the allocation fails (because the system is out of memory),
     372   * the program is terminated.
     373   *
     374   * Since: 2.24
     375   * Returns: a pointer to the allocated memory
     376   */
     377  gpointer
     378  g_malloc_n (gsize n_blocks,
     379  	    gsize n_block_bytes)
     380  {
     381    if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
     382      {
     383        g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
     384                 G_STRLOC, n_blocks, n_block_bytes);
     385      }
     386  
     387    return g_malloc (n_blocks * n_block_bytes);
     388  }
     389  
     390  /**
     391   * g_malloc0_n:
     392   * @n_blocks: the number of blocks to allocate
     393   * @n_block_bytes: the size of each block in bytes
     394   *
     395   * This function is similar to g_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes,
     396   * but care is taken to detect possible overflow during multiplication.
     397   *
     398   * If the allocation fails (because the system is out of memory),
     399   * the program is terminated.
     400   *
     401   * Since: 2.24
     402   * Returns: a pointer to the allocated memory
     403   */
     404  gpointer
     405  g_malloc0_n (gsize n_blocks,
     406  	     gsize n_block_bytes)
     407  {
     408    if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
     409      {
     410        g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
     411                 G_STRLOC, n_blocks, n_block_bytes);
     412      }
     413  
     414    return g_malloc0 (n_blocks * n_block_bytes);
     415  }
     416  
     417  /**
     418   * g_realloc_n:
     419   * @mem: (nullable): the memory to reallocate
     420   * @n_blocks: the number of blocks to allocate
     421   * @n_block_bytes: the size of each block in bytes
     422   *
     423   * This function is similar to g_realloc(), allocating (@n_blocks * @n_block_bytes) bytes,
     424   * but care is taken to detect possible overflow during multiplication.
     425   *
     426   * If the allocation fails (because the system is out of memory),
     427   * the program is terminated.
     428   *
     429   * Since: 2.24
     430   * Returns: the new address of the allocated memory
     431   */
     432  gpointer
     433  g_realloc_n (gpointer mem,
     434  	     gsize    n_blocks,
     435  	     gsize    n_block_bytes)
     436  {
     437    if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
     438      {
     439        g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
     440                 G_STRLOC, n_blocks, n_block_bytes);
     441      }
     442  
     443    return g_realloc (mem, n_blocks * n_block_bytes);
     444  }
     445  
     446  /**
     447   * g_try_malloc_n:
     448   * @n_blocks: the number of blocks to allocate
     449   * @n_block_bytes: the size of each block in bytes
     450   * 
     451   * This function is similar to g_try_malloc(), allocating (@n_blocks * @n_block_bytes) bytes,
     452   * but care is taken to detect possible overflow during multiplication.
     453   * 
     454   * Since: 2.24
     455   * Returns: the allocated memory, or %NULL.
     456   */
     457  gpointer
     458  g_try_malloc_n (gsize n_blocks,
     459  		gsize n_block_bytes)
     460  {
     461    if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
     462      return NULL;
     463  
     464    return g_try_malloc (n_blocks * n_block_bytes);
     465  }
     466  
     467  /**
     468   * g_try_malloc0_n:
     469   * @n_blocks: the number of blocks to allocate
     470   * @n_block_bytes: the size of each block in bytes
     471   * 
     472   * This function is similar to g_try_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes,
     473   * but care is taken to detect possible overflow during multiplication.
     474   * 
     475   * Since: 2.24
     476   * Returns: the allocated memory, or %NULL
     477   */
     478  gpointer
     479  g_try_malloc0_n (gsize n_blocks,
     480  		 gsize n_block_bytes)
     481  {
     482    if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
     483      return NULL;
     484  
     485    return g_try_malloc0 (n_blocks * n_block_bytes);
     486  }
     487  
     488  /**
     489   * g_try_realloc_n:
     490   * @mem: (nullable): previously-allocated memory, or %NULL.
     491   * @n_blocks: the number of blocks to allocate
     492   * @n_block_bytes: the size of each block in bytes
     493   * 
     494   * This function is similar to g_try_realloc(), allocating (@n_blocks * @n_block_bytes) bytes,
     495   * but care is taken to detect possible overflow during multiplication.
     496   * 
     497   * Since: 2.24
     498   * Returns: the allocated memory, or %NULL.
     499   */
     500  gpointer
     501  g_try_realloc_n (gpointer mem,
     502  		 gsize    n_blocks,
     503  		 gsize    n_block_bytes)
     504  {
     505    if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
     506      return NULL;
     507  
     508    return g_try_realloc (mem, n_blocks * n_block_bytes);
     509  }
     510  
     511  /**
     512   * g_mem_is_system_malloc:
     513   * 
     514   * Checks whether the allocator used by g_malloc() is the system's
     515   * malloc implementation. If it returns %TRUE memory allocated with
     516   * malloc() can be used interchangeably with memory allocated using g_malloc().
     517   * This function is useful for avoiding an extra copy of allocated memory returned
     518   * by a non-GLib-based API.
     519   *
     520   * Returns: if %TRUE, malloc() and g_malloc() can be mixed.
     521   *
     522   * Deprecated: 2.46: GLib always uses the system malloc, so this function always
     523   * returns %TRUE.
     524   **/
     525  gboolean
     526  g_mem_is_system_malloc (void)
     527  {
     528    return TRUE;
     529  }
     530  
     531  /**
     532   * g_mem_set_vtable:
     533   * @vtable: table of memory allocation routines.
     534   * 
     535   * This function used to let you override the memory allocation function.
     536   * However, its use was incompatible with the use of global constructors
     537   * in GLib and GIO, because those use the GLib allocators before main is
     538   * reached. Therefore this function is now deprecated and is just a stub.
     539   *
     540   * Deprecated: 2.46: This function now does nothing. Use other memory
     541   * profiling tools instead
     542   */
     543  void
     544  g_mem_set_vtable (GMemVTable *vtable)
     545  {
     546    g_warning (G_STRLOC ": custom memory allocation vtable not supported");
     547  }
     548  
     549  
     550  /**
     551   * glib_mem_profiler_table:
     552   *
     553   * Used to be a #GMemVTable containing profiling variants of the memory
     554   * allocation functions, but this variable shouldn't be modified anymore.
     555   *
     556   * Deprecated: 2.46: Use other memory profiling tools instead
     557   */
     558  GMemVTable *glib_mem_profiler_table = &glib_mem_vtable;
     559  
     560  /**
     561   * g_mem_profile:
     562   *
     563   * GLib used to support some tools for memory profiling, but this
     564   * no longer works. There are many other useful tools for memory
     565   * profiling these days which can be used instead.
     566   *
     567   * Deprecated: 2.46: Use other memory profiling tools instead
     568   */
     569  void
     570  g_mem_profile (void)
     571  {
     572    g_warning (G_STRLOC ": memory profiling not supported");
     573  }
     574  
     575  /**
     576   * g_aligned_alloc:
     577   * @n_blocks: the number of blocks to allocate
     578   * @n_block_bytes: the size of each block in bytes
     579   * @alignment: the alignment to be enforced, which must be a positive power of 2
     580   *   and a multiple of `sizeof(void*)`
     581   *
     582   * This function is similar to g_malloc(), allocating (@n_blocks * @n_block_bytes)
     583   * bytes, but care is taken to align the allocated memory to with the given
     584   * alignment value. Additionally, it will detect possible overflow during
     585   * multiplication.
     586   *
     587   * If the allocation fails (because the system is out of memory),
     588   * the program is terminated.
     589   *
     590   * Aligned memory allocations returned by this function can only be
     591   * freed using g_aligned_free_sized() or g_aligned_free().
     592   *
     593   * Returns: (transfer full): the allocated memory
     594   *
     595   * Since: 2.72
     596   */
     597  gpointer
     598  g_aligned_alloc (gsize n_blocks,
     599                   gsize n_block_bytes,
     600                   gsize alignment)
     601  {
     602    gpointer res = NULL;
     603    gsize real_size;
     604  
     605    if (G_UNLIKELY ((alignment == 0) || (alignment & (alignment - 1)) != 0))
     606      {
     607        g_error ("%s: alignment %"G_GSIZE_FORMAT" must be a positive power of two",
     608                 G_STRLOC, alignment);
     609      }
     610  
     611    if (G_UNLIKELY ((alignment % sizeof (void *)) != 0))
     612      {
     613        g_error ("%s: alignment %"G_GSIZE_FORMAT" must be a multiple of %"G_GSIZE_FORMAT,
     614                 G_STRLOC, alignment, sizeof (void *));
     615      }
     616  
     617    if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
     618      {
     619        g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
     620                 G_STRLOC, n_blocks, n_block_bytes);
     621      }
     622  
     623    real_size = n_blocks * n_block_bytes;
     624  
     625    if (G_UNLIKELY (real_size == 0))
     626      {
     627        TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) real_size, 0, 0));
     628        return NULL;
     629      }
     630  
     631    /* We need to clear errno because posix_memalign() will use its return
     632     * value in the same way memalign() and aligned_alloc() will set errno.
     633     * Additionally, posix_memalign() will warn if its return value is left
     634     * unassigned.
     635     *
     636     * We handle all possible return values (ENOMEM and EINVAL) with either
     637     * precondition or postcondition checking.
     638     */
     639    errno = 0;
     640  
     641  #if defined(HAVE_POSIX_MEMALIGN)
     642    errno = posix_memalign (&res, alignment, real_size);
     643  #elif defined(HAVE_ALIGNED_ALLOC) || defined(HAVE__ALIGNED_MALLOC)
     644    /* real_size must be a multiple of alignment */
     645    if (real_size % alignment != 0)
     646      {
     647        gsize offset = real_size % alignment;
     648  
     649        if (G_MAXSIZE - real_size < (alignment - offset))
     650          {
     651            g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"+%"G_GSIZE_FORMAT" bytes",
     652                     G_STRLOC, real_size, (alignment - offset));
     653          }
     654  
     655        real_size += (alignment - offset);
     656      }
     657  
     658    res = aligned_alloc (alignment, real_size);
     659  #elif defined(HAVE_MEMALIGN)
     660    res = memalign (alignment, real_size);
     661  #else
     662  # error "This platform does not have an aligned memory allocator."
     663  #endif
     664  
     665    TRACE (GLIB_MEM_ALLOC((void*) res, (unsigned int) real_size, 0, 0));
     666    if (res)
     667      return res;
     668  
     669    g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
     670             G_STRLOC, real_size);
     671  
     672    return NULL;
     673  }
     674  
     675  /**
     676   * g_aligned_alloc0:
     677   * @n_blocks: the number of blocks to allocate
     678   * @n_block_bytes: the size of each block in bytes
     679   * @alignment: the alignment to be enforced, which must be a positive power of 2
     680   *   and a multiple of `sizeof(void*)`
     681   *
     682   * This function is similar to g_aligned_alloc(), but it will
     683   * also clear the allocated memory before returning it.
     684   *
     685   * Returns: (transfer full): the allocated, cleared memory
     686   *
     687   * Since: 2.72
     688   */
     689  gpointer
     690  g_aligned_alloc0 (gsize n_blocks,
     691                    gsize n_block_bytes,
     692                    gsize alignment)
     693  {
     694    gpointer res = g_aligned_alloc (n_blocks, n_block_bytes, alignment);
     695  
     696    if (G_LIKELY (res != NULL))
     697      memset (res, 0, n_blocks * n_block_bytes);
     698  
     699    return res;
     700  }
     701  
     702  /**
     703   * g_aligned_free:
     704   * @mem: (nullable): the memory to deallocate
     705   *
     706   * Frees the memory allocated by g_aligned_alloc().
     707   *
     708   * Since: 2.72
     709   */
     710  void
     711  g_aligned_free (gpointer mem)
     712  {
     713    aligned_free (mem);
     714  }
     715  
     716  /**
     717   * g_aligned_free_sized:
     718   * @mem: (nullable): the memory to free
     719   * @alignment: alignment of @mem
     720   * @size: size of @mem, in bytes
     721   *
     722   * Frees the memory pointed to by @mem, assuming it is has the given @size and
     723   * @alignment.
     724   *
     725   * If @mem is %NULL this is a no-op (and @size is ignored).
     726   *
     727   * It is an error if @size doesn’t match the size, or @alignment doesn’t match
     728   * the alignment, passed when @mem was allocated. @size and @alignment are
     729   * passed to this function to allow optimizations in the allocator. If you
     730   * don’t know either of them, use g_aligned_free() instead.
     731   *
     732   * Since: 2.76
     733   */
     734  void
     735  g_aligned_free_sized (void   *mem,
     736                        size_t  alignment,
     737                        size_t  size)
     738  {
     739  #ifdef HAVE_FREE_ALIGNED_SIZED
     740    free_aligned_sized (mem, alignment, size);
     741  #else
     742    aligned_free (mem);
     743  #endif
     744  }