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 }