Branch data Line data Source code
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 : 82327701 : g_malloc (gsize n_bytes)
95 : : {
96 : 82327701 : if (G_LIKELY (n_bytes))
97 : : {
98 : : gpointer mem;
99 : :
100 : 82310031 : mem = malloc (n_bytes);
101 : 82310031 : TRACE (GLIB_MEM_ALLOC ((void *) mem, n_bytes, 0, 0));
102 : 82310031 : if (mem)
103 : 82310031 : return mem;
104 : :
105 : 0 : g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
106 : : G_STRLOC, n_bytes);
107 : : }
108 : :
109 : 17670 : TRACE (GLIB_MEM_ALLOC ((void *) NULL, n_bytes, 0, 0));
110 : :
111 : 17670 : 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 : 14736771 : g_malloc0 (gsize n_bytes)
128 : : {
129 : 14736771 : if (G_LIKELY (n_bytes))
130 : : {
131 : : gpointer mem;
132 : :
133 : 14736708 : mem = calloc (1, n_bytes);
134 : 14736708 : TRACE (GLIB_MEM_ALLOC ((void *) mem, n_bytes, 1, 0));
135 : 14736708 : if (mem)
136 : 14736708 : return mem;
137 : :
138 : 0 : g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
139 : : G_STRLOC, n_bytes);
140 : : }
141 : :
142 : 63 : TRACE (GLIB_MEM_ALLOC ((void *) NULL, n_bytes, 1, 0));
143 : :
144 : 63 : 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 : 5362349 : g_realloc (gpointer mem,
165 : : gsize n_bytes)
166 : : {
167 : : gpointer newmem;
168 : :
169 : 5362349 : if (G_LIKELY (n_bytes))
170 : : {
171 : 5360257 : newmem = realloc (mem, n_bytes);
172 : 5360257 : TRACE (GLIB_MEM_REALLOC ((void *) newmem, (void *) mem, n_bytes, 0));
173 : 5360257 : if (newmem)
174 : 5360257 : return newmem;
175 : :
176 : 0 : g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
177 : : G_STRLOC, n_bytes);
178 : : }
179 : :
180 : 2092 : free (mem);
181 : :
182 : 2092 : TRACE (GLIB_MEM_REALLOC((void*) NULL, (void*)mem, 0, 0));
183 : :
184 : 2092 : 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 : 74647890 : (g_free) (gpointer mem)
207 : : {
208 : 74647890 : free (mem);
209 : 74647890 : TRACE(GLIB_MEM_FREE((void*) mem));
210 : 74647890 : }
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 : 48265960 : g_free_sized (void *mem,
233 : : size_t size)
234 : : {
235 : : #ifdef HAVE_FREE_SIZED
236 : : free_sized (mem, size);
237 : : #else
238 : 48265960 : free (mem);
239 : : #endif
240 : 48265960 : TRACE (GLIB_MEM_FREE ((void*) mem));
241 : 48265960 : }
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 [callback@GLib.DestroyNotify] using the
261 : : * standard calling convention for the platform that GLib was compiled for;
262 : : * otherwise the program will experience undefined behaviour.
263 : : *
264 : : * Examples of this kind of undefined behaviour include using many Windows Win32
265 : : * APIs, as well as many if not all OpenGL and Vulkan calls on 32-bit Windows,
266 : : * which typically use the `__stdcall` calling convention rather than the
267 : : * `__cdecl` calling convention.
268 : : *
269 : : * The affected functions can be used by wrapping them in a
270 : : * [callback@GLib.DestroyNotify] that is declared with the standard calling
271 : : * convention:
272 : : *
273 : : * ```c
274 : : * // Wrapper needed to avoid mismatched calling conventions on Windows
275 : : * static void
276 : : * destroy_sync (void *sync)
277 : : * {
278 : : * glDeleteSync (sync);
279 : : * }
280 : : *
281 : : * // …
282 : : *
283 : : * g_clear_pointer (&sync, destroy_sync);
284 : : * ```
285 : :
286 : : *
287 : : * Since: 2.34
288 : : **/
289 : : #undef g_clear_pointer
290 : : void
291 : 6 : g_clear_pointer (gpointer *pp,
292 : : GDestroyNotify destroy)
293 : : {
294 : : gpointer _p;
295 : :
296 : 6 : _p = *pp;
297 : 6 : if (_p)
298 : : {
299 : 6 : *pp = NULL;
300 : 6 : destroy (_p);
301 : : }
302 : 6 : }
303 : :
304 : : /**
305 : : * g_try_malloc:
306 : : * @n_bytes: number of bytes to allocate.
307 : : *
308 : : * Attempts to allocate @n_bytes, and returns %NULL on failure.
309 : : * Contrast with g_malloc(), which aborts the program on failure.
310 : : *
311 : : * Returns: the allocated memory, or %NULL.
312 : : */
313 : : gpointer
314 : 407401 : g_try_malloc (gsize n_bytes)
315 : : {
316 : : gpointer mem;
317 : :
318 : 407401 : if (G_LIKELY (n_bytes))
319 : 407395 : mem = malloc (n_bytes);
320 : : else
321 : 6 : mem = NULL;
322 : :
323 : 407401 : TRACE (GLIB_MEM_ALLOC ((void *) mem, n_bytes, 0, 1));
324 : :
325 : 407401 : return mem;
326 : : }
327 : :
328 : : /**
329 : : * g_try_malloc0:
330 : : * @n_bytes: number of bytes to allocate
331 : : *
332 : : * Attempts to allocate @n_bytes, initialized to 0's, and returns %NULL on
333 : : * failure. Contrast with g_malloc0(), which aborts the program on failure.
334 : : *
335 : : * Since: 2.8
336 : : * Returns: the allocated memory, or %NULL
337 : : */
338 : : gpointer
339 : 8 : g_try_malloc0 (gsize n_bytes)
340 : : {
341 : : gpointer mem;
342 : :
343 : 8 : if (G_LIKELY (n_bytes))
344 : 2 : mem = calloc (1, n_bytes);
345 : : else
346 : 6 : mem = NULL;
347 : :
348 : 8 : return mem;
349 : : }
350 : :
351 : : /**
352 : : * g_try_realloc:
353 : : * @mem: (nullable): previously-allocated memory, or %NULL.
354 : : * @n_bytes: number of bytes to allocate.
355 : : *
356 : : * Attempts to realloc @mem to a new size, @n_bytes, and returns %NULL
357 : : * on failure. Contrast with g_realloc(), which aborts the program
358 : : * on failure.
359 : : *
360 : : * If @mem is %NULL, behaves the same as g_try_malloc().
361 : : *
362 : : * Returns: the allocated memory, or %NULL.
363 : : */
364 : : gpointer
365 : 42 : g_try_realloc (gpointer mem,
366 : : gsize n_bytes)
367 : : {
368 : : gpointer newmem;
369 : :
370 : 42 : if (G_LIKELY (n_bytes))
371 : 36 : newmem = realloc (mem, n_bytes);
372 : : else
373 : : {
374 : 6 : newmem = NULL;
375 : 6 : free (mem);
376 : : }
377 : :
378 : 42 : TRACE (GLIB_MEM_REALLOC ((void *) newmem, (void *) mem, n_bytes, 1));
379 : :
380 : 42 : return newmem;
381 : : }
382 : :
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 : : * If the allocation fails (because the system is out of memory),
393 : : * the program is terminated.
394 : : *
395 : : * Since: 2.24
396 : : * Returns: a pointer to the allocated memory
397 : : */
398 : : gpointer
399 : 22219927 : g_malloc_n (gsize n_blocks,
400 : : gsize n_block_bytes)
401 : : {
402 : : size_t len;
403 : :
404 : 22219927 : if (!g_size_checked_mul (&len, n_blocks, n_block_bytes))
405 : : {
406 : 0 : g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
407 : : G_STRLOC, n_blocks, n_block_bytes);
408 : : }
409 : :
410 : 22219927 : return g_malloc (len);
411 : : }
412 : :
413 : : /**
414 : : * g_malloc0_n:
415 : : * @n_blocks: the number of blocks to allocate
416 : : * @n_block_bytes: the size of each block in bytes
417 : : *
418 : : * This function is similar to g_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes,
419 : : * but care is taken to detect possible overflow during multiplication.
420 : : *
421 : : * If the allocation fails (because the system is out of memory),
422 : : * the program is terminated.
423 : : *
424 : : * Since: 2.24
425 : : * Returns: a pointer to the allocated memory
426 : : */
427 : : gpointer
428 : 4783537 : g_malloc0_n (gsize n_blocks,
429 : : gsize n_block_bytes)
430 : : {
431 : : size_t len;
432 : :
433 : 4783537 : if (!g_size_checked_mul (&len, n_blocks, n_block_bytes))
434 : : {
435 : 0 : g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
436 : : G_STRLOC, n_blocks, n_block_bytes);
437 : : }
438 : :
439 : 4783537 : return g_malloc0 (len);
440 : : }
441 : :
442 : : /**
443 : : * g_realloc_n:
444 : : * @mem: (nullable): the memory to reallocate
445 : : * @n_blocks: the number of blocks to allocate
446 : : * @n_block_bytes: the size of each block in bytes
447 : : *
448 : : * This function is similar to g_realloc(), allocating (@n_blocks * @n_block_bytes) bytes,
449 : : * but care is taken to detect possible overflow during multiplication.
450 : : *
451 : : * If the allocation fails (because the system is out of memory),
452 : : * the program is terminated.
453 : : *
454 : : * Since: 2.24
455 : : * Returns: the new address of the allocated memory
456 : : */
457 : : gpointer
458 : 383380 : g_realloc_n (gpointer mem,
459 : : gsize n_blocks,
460 : : gsize n_block_bytes)
461 : : {
462 : : size_t len;
463 : :
464 : 383380 : if (!g_size_checked_mul (&len, n_blocks, n_block_bytes))
465 : : {
466 : 0 : g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
467 : : G_STRLOC, n_blocks, n_block_bytes);
468 : : }
469 : :
470 : 383380 : return g_realloc (mem, len);
471 : : }
472 : :
473 : : /**
474 : : * g_try_malloc_n:
475 : : * @n_blocks: the number of blocks to allocate
476 : : * @n_block_bytes: the size of each block in bytes
477 : : *
478 : : * This function is similar to g_try_malloc(), allocating (@n_blocks * @n_block_bytes) bytes,
479 : : * but care is taken to detect possible overflow during multiplication.
480 : : *
481 : : * Since: 2.24
482 : : * Returns: the allocated memory, or %NULL.
483 : : */
484 : : gpointer
485 : 406570 : g_try_malloc_n (gsize n_blocks,
486 : : gsize n_block_bytes)
487 : : {
488 : : size_t len;
489 : :
490 : 406570 : if (!g_size_checked_mul (&len, n_blocks, n_block_bytes))
491 : 4 : return NULL;
492 : :
493 : 406566 : return g_try_malloc (len);
494 : : }
495 : :
496 : : /**
497 : : * g_try_malloc0_n:
498 : : * @n_blocks: the number of blocks to allocate
499 : : * @n_block_bytes: the size of each block in bytes
500 : : *
501 : : * This function is similar to g_try_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes,
502 : : * but care is taken to detect possible overflow during multiplication.
503 : : *
504 : : * Since: 2.24
505 : : * Returns: the allocated memory, or %NULL
506 : : */
507 : : gpointer
508 : 6 : g_try_malloc0_n (gsize n_blocks,
509 : : gsize n_block_bytes)
510 : : {
511 : : size_t len;
512 : :
513 : 6 : if (!g_size_checked_mul (&len, n_blocks, n_block_bytes))
514 : 4 : return NULL;
515 : :
516 : 2 : return g_try_malloc0 (len);
517 : : }
518 : :
519 : : /**
520 : : * g_try_realloc_n:
521 : : * @mem: (nullable): previously-allocated memory, or %NULL.
522 : : * @n_blocks: the number of blocks to allocate
523 : : * @n_block_bytes: the size of each block in bytes
524 : : *
525 : : * This function is similar to g_try_realloc(), allocating (@n_blocks * @n_block_bytes) bytes,
526 : : * but care is taken to detect possible overflow during multiplication.
527 : : *
528 : : * Since: 2.24
529 : : * Returns: the allocated memory, or %NULL.
530 : : */
531 : : gpointer
532 : 6 : g_try_realloc_n (gpointer mem,
533 : : gsize n_blocks,
534 : : gsize n_block_bytes)
535 : : {
536 : : size_t len;
537 : :
538 : 6 : if (!g_size_checked_mul (&len, n_blocks, n_block_bytes))
539 : 4 : return NULL;
540 : :
541 : 2 : return g_try_realloc (mem, len);
542 : : }
543 : :
544 : : /**
545 : : * g_mem_is_system_malloc:
546 : : *
547 : : * Checks whether the allocator used by g_malloc() is the system's
548 : : * malloc implementation. If it returns %TRUE memory allocated with
549 : : * malloc() can be used interchangeably with memory allocated using g_malloc().
550 : : * This function is useful for avoiding an extra copy of allocated memory returned
551 : : * by a non-GLib-based API.
552 : : *
553 : : * Returns: if %TRUE, malloc() and g_malloc() can be mixed.
554 : : *
555 : : * Deprecated: 2.46: GLib always uses the system malloc, so this function always
556 : : * returns %TRUE.
557 : : **/
558 : : gboolean
559 : 0 : g_mem_is_system_malloc (void)
560 : : {
561 : 0 : return TRUE;
562 : : }
563 : :
564 : : /**
565 : : * g_mem_set_vtable:
566 : : * @vtable: table of memory allocation routines.
567 : : *
568 : : * This function used to let you override the memory allocation function.
569 : : * However, its use was incompatible with the use of global constructors
570 : : * in GLib and GIO, because those use the GLib allocators before main is
571 : : * reached. Therefore this function is now deprecated and is just a stub.
572 : : *
573 : : * Deprecated: 2.46: This function now does nothing. Use other memory
574 : : * profiling tools instead
575 : : */
576 : : void
577 : 0 : g_mem_set_vtable (GMemVTable *vtable)
578 : : {
579 : 0 : g_warning (G_STRLOC ": custom memory allocation vtable not supported");
580 : 0 : }
581 : :
582 : :
583 : : /**
584 : : * glib_mem_profiler_table:
585 : : *
586 : : * Used to be a #GMemVTable containing profiling variants of the memory
587 : : * allocation functions, but this variable shouldn't be modified anymore.
588 : : *
589 : : * Deprecated: 2.46: Use other memory profiling tools instead
590 : : */
591 : : GMemVTable *glib_mem_profiler_table = &glib_mem_vtable;
592 : :
593 : : /**
594 : : * g_mem_profile:
595 : : *
596 : : * GLib used to support some tools for memory profiling, but this
597 : : * no longer works. There are many other useful tools for memory
598 : : * profiling these days which can be used instead.
599 : : *
600 : : * Deprecated: 2.46: Use other memory profiling tools instead
601 : : */
602 : : void
603 : 0 : g_mem_profile (void)
604 : : {
605 : 0 : g_warning (G_STRLOC ": memory profiling not supported");
606 : 0 : }
607 : :
608 : : /**
609 : : * g_aligned_alloc:
610 : : * @n_blocks: the number of blocks to allocate
611 : : * @n_block_bytes: the size of each block in bytes
612 : : * @alignment: the alignment to be enforced, which must be a positive power of 2
613 : : * and a multiple of `sizeof(void*)`
614 : : *
615 : : * This function is similar to g_malloc(), allocating (@n_blocks * @n_block_bytes)
616 : : * bytes, but care is taken to align the allocated memory to with the given
617 : : * alignment value. Additionally, it will detect possible overflow during
618 : : * multiplication.
619 : : *
620 : : * If the allocation fails (because the system is out of memory),
621 : : * the program is terminated.
622 : : *
623 : : * Aligned memory allocations returned by this function can only be
624 : : * freed using g_aligned_free_sized() or g_aligned_free().
625 : : *
626 : : * Returns: (transfer full): the allocated memory
627 : : *
628 : : * Since: 2.72
629 : : */
630 : : gpointer
631 : 38 : g_aligned_alloc (gsize n_blocks,
632 : : gsize n_block_bytes,
633 : : gsize alignment)
634 : : {
635 : 38 : gpointer res = NULL;
636 : : gsize real_size;
637 : :
638 : 38 : if (G_UNLIKELY ((alignment == 0) || (alignment & (alignment - 1)) != 0))
639 : : {
640 : 0 : g_error ("%s: alignment %"G_GSIZE_FORMAT" must be a positive power of two",
641 : : G_STRLOC, alignment);
642 : : }
643 : :
644 : 38 : if (G_UNLIKELY ((alignment % sizeof (void *)) != 0))
645 : : {
646 : 0 : g_error ("%s: alignment %"G_GSIZE_FORMAT" must be a multiple of %"G_GSIZE_FORMAT,
647 : : G_STRLOC, alignment, sizeof (void *));
648 : : }
649 : :
650 : 38 : if (!g_size_checked_mul (&real_size, n_blocks, n_block_bytes))
651 : : {
652 : 0 : g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
653 : : G_STRLOC, n_blocks, n_block_bytes);
654 : : }
655 : :
656 : 38 : if (G_UNLIKELY (real_size == 0))
657 : : {
658 : 18 : TRACE (GLIB_MEM_ALLOC ((void *) NULL, real_size, 0, 0));
659 : 18 : return NULL;
660 : : }
661 : :
662 : : /* We need to clear errno because posix_memalign() will use its return
663 : : * value in the same way memalign() and aligned_alloc() will set errno.
664 : : * Additionally, posix_memalign() will warn if its return value is left
665 : : * unassigned.
666 : : *
667 : : * We handle all possible return values (ENOMEM and EINVAL) with either
668 : : * precondition or postcondition checking.
669 : : */
670 : 20 : errno = 0;
671 : :
672 : : #if defined(HAVE_POSIX_MEMALIGN)
673 : 20 : errno = posix_memalign (&res, alignment, real_size);
674 : : #elif defined(HAVE_ALIGNED_ALLOC) || defined(HAVE__ALIGNED_MALLOC)
675 : : /* real_size must be a multiple of alignment */
676 : : if (real_size % alignment != 0)
677 : : {
678 : : gsize offset = real_size % alignment;
679 : :
680 : : if (G_MAXSIZE - real_size < (alignment - offset))
681 : : {
682 : : g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"+%"G_GSIZE_FORMAT" bytes",
683 : : G_STRLOC, real_size, (alignment - offset));
684 : : }
685 : :
686 : : real_size += (alignment - offset);
687 : : }
688 : :
689 : : res = aligned_alloc (alignment, real_size);
690 : : #elif defined(HAVE_MEMALIGN)
691 : : res = memalign (alignment, real_size);
692 : : #else
693 : : # error "This platform does not have an aligned memory allocator."
694 : : #endif
695 : :
696 : 20 : TRACE (GLIB_MEM_ALLOC ((void *) res, real_size, 0, 0));
697 : 20 : if (res)
698 : 20 : return res;
699 : :
700 : 0 : g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
701 : : G_STRLOC, real_size);
702 : :
703 : : return NULL;
704 : : }
705 : :
706 : : /**
707 : : * g_aligned_alloc0:
708 : : * @n_blocks: the number of blocks to allocate
709 : : * @n_block_bytes: the size of each block in bytes
710 : : * @alignment: the alignment to be enforced, which must be a positive power of 2
711 : : * and a multiple of `sizeof(void*)`
712 : : *
713 : : * This function is similar to g_aligned_alloc(), but it will
714 : : * also clear the allocated memory before returning it.
715 : : *
716 : : * Returns: (transfer full): the allocated, cleared memory
717 : : *
718 : : * Since: 2.72
719 : : */
720 : : gpointer
721 : 13 : g_aligned_alloc0 (gsize n_blocks,
722 : : gsize n_block_bytes,
723 : : gsize alignment)
724 : : {
725 : 13 : gpointer res = g_aligned_alloc (n_blocks, n_block_bytes, alignment);
726 : :
727 : 13 : if (G_LIKELY (res != NULL))
728 : 7 : memset (res, 0, n_blocks * n_block_bytes);
729 : :
730 : 13 : return res;
731 : : }
732 : :
733 : : /**
734 : : * g_aligned_free:
735 : : * @mem: (nullable): the memory to deallocate
736 : : *
737 : : * Frees the memory allocated by g_aligned_alloc().
738 : : *
739 : : * Since: 2.72
740 : : */
741 : : void
742 : 14 : g_aligned_free (gpointer mem)
743 : : {
744 : 14 : aligned_free (mem);
745 : 14 : }
746 : :
747 : : /**
748 : : * g_aligned_free_sized:
749 : : * @mem: (nullable): the memory to free
750 : : * @alignment: alignment of @mem
751 : : * @size: size of @mem, in bytes
752 : : *
753 : : * Frees the memory pointed to by @mem, assuming it is has the given @size and
754 : : * @alignment.
755 : : *
756 : : * If @mem is %NULL this is a no-op (and @size is ignored).
757 : : *
758 : : * It is an error if @size doesn’t match the size, or @alignment doesn’t match
759 : : * the alignment, passed when @mem was allocated. @size and @alignment are
760 : : * passed to this function to allow optimizations in the allocator. If you
761 : : * don’t know either of them, use g_aligned_free() instead.
762 : : *
763 : : * Since: 2.76
764 : : */
765 : : void
766 : 12 : g_aligned_free_sized (void *mem,
767 : : size_t alignment,
768 : : size_t size)
769 : : {
770 : : #ifdef HAVE_FREE_ALIGNED_SIZED
771 : : free_aligned_sized (mem, alignment, size);
772 : : #else
773 : 12 : aligned_free (mem);
774 : : #endif
775 : 12 : }
|