diff options
| author | Ken Brown | 2014-08-28 10:48:02 -0400 |
|---|---|---|
| committer | Ken Brown | 2014-08-28 10:48:02 -0400 |
| commit | ea652500776aacbb8cb64f9ecca16a2d2c7add80 (patch) | |
| tree | c759fc62dfa422e8fb636aef6dbb04df2c68cc7e /src/gmalloc.c | |
| parent | a7ef7a0e53ae1f391f4bda207bb5e9b9d833d354 (diff) | |
| download | emacs-ea652500776aacbb8cb64f9ecca16a2d2c7add80.tar.gz emacs-ea652500776aacbb8cb64f9ecca16a2d2c7add80.zip | |
Add support for HYBRID_MALLOC, allowing the use of gmalloc before
dumping and the system malloc after dumping. (Bug#18222)
* configure.ac (HYBRID_MALLOC): New macro; define to use gmalloc
before dumping and the system malloc after dumping. Define on Cygwin.
* src/conf_post.h (malloc, realloc, calloc, free) [HYBRID_MALLOC]:
Define as macros, expanding to hybrid_malloc, etc.
(HYBRID_GET_CURRENT_DIR_NAME): New macro.
(get_current_dir_name) [HYBRID_GET_CURRENT_DIR_NAME]: Define as
macro.
* src/gmalloc.c: Set up the infrastructure for HYBRID_MALLOC, with a
full implementation on Cygwin. Remove Cygwin-specific code that
is no longer needed.
(malloc, realloc, calloc, free, aligned_alloc) [HYBRID_MALLOC]:
Redefine as macros expanding to gmalloc, grealloc, etc.
(DUMPED, ALLOCATED_BEFORE_DUMPING) [CYGWIN]: New macros.
(get_current_dir_name) [HYBRID_GET_CURRENT_DIR_NAME]: Undefine.
(USE_PTHREAD, posix_memalign) [HYBRID_MALLOC]: Don't define.
(hybrid_malloc, hybrid_calloc, hybrid_free, hybrid_realloc)
[HYBRID_MALLOC]:
(hybrid_get_current_dir_name) [HYBRID_GET_CURRENT_DIR_NAME]:
(hybrid_aligned_alloc) [HYBRID_MALLOC && (HAVE_ALIGNED_ALLOC ||
HAVE_POSIX_MEMALIGN)]: New functions.
* src/alloc.c (aligned_alloc) [HYBRID_MALLOC && (ALIGNED_ALLOC ||
HAVE_POSIX_MEMALIGN)]: Define as macro expanding to
hybrid_aligned_alloc; declare.
(USE_ALIGNED_ALLOC) [HYBRID_MALLOC && (ALIGNED_ALLOC ||
HAVE_POSIX_MEMALIGN)]: Define.
(refill_memory_reserve) [HYBRID_MALLOC]: Do nothing.
* src/sysdep.c (get_current_dir_name) [HYBRID_GET_CURRENT_DIR_NAME]:
Define as macro, expanding to gget_current_dir_name, and define
the latter.
* src/emacs.c (main) [HYBRID_MALLOC]: Don't call memory_warnings() or
malloc_enable_thread(). Don't initialize malloc.
* src/lisp.h (NONPOINTER_BITS) [CYGWIN]: Define (because GNU_MALLOC is
no longer defined on Cygwin).
(refill_memory_reserve) [HYBRID_MALLOC]: Don't declare.
* src/sheap.c (bss_sbrk_buffer_end): New variable.
* src/unexcw.c (__malloc_initialized): Remove variable.
* src/ralloc.c: Throughout, treat HYBRID_MALLOC the same as
SYSTEM_MALLOC.
* src/xdisp.c (decode_mode_spec) [HYBRID_MALLOC]: Don't check
Vmemory_full.
Diffstat (limited to 'src/gmalloc.c')
| -rw-r--r-- | src/gmalloc.c | 231 |
1 files changed, 149 insertions, 82 deletions
diff --git a/src/gmalloc.c b/src/gmalloc.c index 27965e37539..f4a32c79ca1 100644 --- a/src/gmalloc.c +++ b/src/gmalloc.c | |||
| @@ -19,15 +19,27 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. | |||
| 19 | The author may be reached (Email) at the address mike@ai.mit.edu, | 19 | The author may be reached (Email) at the address mike@ai.mit.edu, |
| 20 | or (US mail) as Mike Haertel c/o Free Software Foundation. */ | 20 | or (US mail) as Mike Haertel c/o Free Software Foundation. */ |
| 21 | 21 | ||
| 22 | /* If HYBRID_MALLOC is defined in config.h, then conf_post.h #defines | ||
| 23 | malloc and friends as macros before including stdlib.h. In this | ||
| 24 | file we will need the prototypes for the system malloc, so we must | ||
| 25 | include stdlib.h before config.h. And we have to do this | ||
| 26 | unconditionally, since HYBRID_MALLOC hasn't been defined yet. */ | ||
| 27 | #include <stdlib.h> | ||
| 28 | |||
| 22 | #include <config.h> | 29 | #include <config.h> |
| 23 | 30 | ||
| 24 | #ifdef HAVE_PTHREAD | 31 | #if defined HAVE_PTHREAD && !defined HYBRID_MALLOC |
| 25 | #define USE_PTHREAD | 32 | #define USE_PTHREAD |
| 26 | #endif | 33 | #endif |
| 27 | 34 | ||
| 28 | #include <string.h> | 35 | #include <string.h> |
| 29 | #include <limits.h> | 36 | #include <limits.h> |
| 30 | #include <stdint.h> | 37 | #include <stdint.h> |
| 38 | |||
| 39 | #ifdef HYBRID_GET_CURRENT_DIR_NAME | ||
| 40 | #undef get_current_dir_name | ||
| 41 | #endif | ||
| 42 | |||
| 31 | #include <unistd.h> | 43 | #include <unistd.h> |
| 32 | 44 | ||
| 33 | #ifdef USE_PTHREAD | 45 | #ifdef USE_PTHREAD |
| @@ -42,6 +54,41 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. | |||
| 42 | extern void emacs_abort (void); | 54 | extern void emacs_abort (void); |
| 43 | #endif | 55 | #endif |
| 44 | 56 | ||
| 57 | /* If HYBRID_MALLOC is defined, then temacs will use malloc, | ||
| 58 | realloc... as defined in this file (and renamed gmalloc, | ||
| 59 | grealloc... via the macros that follow). The dumped emacs, | ||
| 60 | however, will use the system malloc, realloc.... In other source | ||
| 61 | files, malloc, realloc... are renamed hybrid_malloc, | ||
| 62 | hybrid_realloc... via macros in conf_post.h. hybrid_malloc and | ||
| 63 | friends are wrapper functions defined later in this file. | ||
| 64 | aligned_alloc is defined as a macro only in alloc.c. | ||
| 65 | |||
| 66 | As of this writing (August 2014), Cygwin is the only platform on | ||
| 67 | which HYBRID_MACRO is defined. Any other platform that wants to | ||
| 68 | define it will have to define the macros DUMPED and | ||
| 69 | ALLOCATED_BEFORE_DUMPING, defined below for Cygwin. */ | ||
| 70 | #ifdef HYBRID_MALLOC | ||
| 71 | #undef malloc | ||
| 72 | #undef realloc | ||
| 73 | #undef calloc | ||
| 74 | #undef free | ||
| 75 | #define malloc gmalloc | ||
| 76 | #define realloc grealloc | ||
| 77 | #define calloc gcalloc | ||
| 78 | #define aligned_alloc galigned_alloc | ||
| 79 | #define free gfree | ||
| 80 | #endif /* HYBRID_MALLOC */ | ||
| 81 | |||
| 82 | #ifdef CYGWIN | ||
| 83 | extern void *bss_sbrk (ptrdiff_t size); | ||
| 84 | extern int bss_sbrk_did_unexec; | ||
| 85 | extern char *bss_sbrk_buffer; | ||
| 86 | extern char *bss_sbrk_buffer_end; | ||
| 87 | #define DUMPED bss_sbrk_did_unexec | ||
| 88 | #define ALLOCATED_BEFORE_DUMPING(P) \ | ||
| 89 | ((char *) (P) < bss_sbrk_buffer_end && (char *) (P) >= bss_sbrk_buffer) | ||
| 90 | #endif | ||
| 91 | |||
| 45 | #ifdef __cplusplus | 92 | #ifdef __cplusplus |
| 46 | extern "C" | 93 | extern "C" |
| 47 | { | 94 | { |
| @@ -306,22 +353,6 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. | |||
| 306 | 353 | ||
| 307 | #include <errno.h> | 354 | #include <errno.h> |
| 308 | 355 | ||
| 309 | /* On Cygwin there are two heaps. temacs uses the static heap | ||
| 310 | (defined in sheap.c and managed with bss_sbrk), and the dumped | ||
| 311 | emacs uses the Cygwin heap (managed with sbrk). When emacs starts | ||
| 312 | on Cygwin, it reinitializes malloc, and we save the old info for | ||
| 313 | use by free and realloc if they're called with a pointer into the | ||
| 314 | static heap. | ||
| 315 | |||
| 316 | Currently (2011-08-16) the Cygwin build doesn't use ralloc.c; if | ||
| 317 | this is changed in the future, we'll have to similarly deal with | ||
| 318 | reinitializing ralloc. */ | ||
| 319 | #ifdef CYGWIN | ||
| 320 | extern void *bss_sbrk (ptrdiff_t size); | ||
| 321 | extern int bss_sbrk_did_unexec; | ||
| 322 | char *bss_sbrk_heapbase; /* _heapbase for static heap */ | ||
| 323 | malloc_info *bss_sbrk_heapinfo; /* _heapinfo for static heap */ | ||
| 324 | #endif | ||
| 325 | void *(*__morecore) (ptrdiff_t size) = __default_morecore; | 356 | void *(*__morecore) (ptrdiff_t size) = __default_morecore; |
| 326 | 357 | ||
| 327 | /* Debugging hook for `malloc'. */ | 358 | /* Debugging hook for `malloc'. */ |
| @@ -490,18 +521,8 @@ register_heapinfo (void) | |||
| 490 | } | 521 | } |
| 491 | 522 | ||
| 492 | #ifdef USE_PTHREAD | 523 | #ifdef USE_PTHREAD |
| 493 | /* On Cygwin prior to 1.7.31, pthread_mutexes were ERRORCHECK mutexes | ||
| 494 | by default. When the default changed to NORMAL in Cygwin-1.7.31, | ||
| 495 | deadlocks occurred (bug#18222). As a temporary workaround, we | ||
| 496 | explicitly set the mutexes to be of ERRORCHECK type, restoring the | ||
| 497 | previous behavior. */ | ||
| 498 | #ifdef CYGWIN | ||
| 499 | pthread_mutex_t _malloc_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; | ||
| 500 | pthread_mutex_t _aligned_blocks_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; | ||
| 501 | #else /* not CYGWIN */ | ||
| 502 | pthread_mutex_t _malloc_mutex = PTHREAD_MUTEX_INITIALIZER; | 524 | pthread_mutex_t _malloc_mutex = PTHREAD_MUTEX_INITIALIZER; |
| 503 | pthread_mutex_t _aligned_blocks_mutex = PTHREAD_MUTEX_INITIALIZER; | 525 | pthread_mutex_t _aligned_blocks_mutex = PTHREAD_MUTEX_INITIALIZER; |
| 504 | #endif /* not CYGWIN */ | ||
| 505 | int _malloc_thread_enabled_p; | 526 | int _malloc_thread_enabled_p; |
| 506 | 527 | ||
| 507 | static void | 528 | static void |
| @@ -536,17 +557,8 @@ malloc_enable_thread (void) | |||
| 536 | initialized mutexes when they are used first. To avoid such a | 557 | initialized mutexes when they are used first. To avoid such a |
| 537 | situation, we initialize mutexes here while their use is | 558 | situation, we initialize mutexes here while their use is |
| 538 | disabled in malloc etc. */ | 559 | disabled in malloc etc. */ |
| 539 | #ifdef CYGWIN | ||
| 540 | /* Use ERRORCHECK mutexes; see comment above. */ | ||
| 541 | pthread_mutexattr_t attr; | ||
| 542 | pthread_mutexattr_init (&attr); | ||
| 543 | pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK); | ||
| 544 | pthread_mutex_init (&_malloc_mutex, &attr); | ||
| 545 | pthread_mutex_init (&_aligned_blocks_mutex, &attr); | ||
| 546 | #else /* not CYGWIN */ | ||
| 547 | pthread_mutex_init (&_malloc_mutex, NULL); | 560 | pthread_mutex_init (&_malloc_mutex, NULL); |
| 548 | pthread_mutex_init (&_aligned_blocks_mutex, NULL); | 561 | pthread_mutex_init (&_aligned_blocks_mutex, NULL); |
| 549 | #endif /* not CYGWIN */ | ||
| 550 | pthread_atfork (malloc_atfork_handler_prepare, | 562 | pthread_atfork (malloc_atfork_handler_prepare, |
| 551 | malloc_atfork_handler_parent, | 563 | malloc_atfork_handler_parent, |
| 552 | malloc_atfork_handler_child); | 564 | malloc_atfork_handler_child); |
| @@ -561,16 +573,6 @@ malloc_initialize_1 (void) | |||
| 561 | mcheck (NULL); | 573 | mcheck (NULL); |
| 562 | #endif | 574 | #endif |
| 563 | 575 | ||
| 564 | #ifdef CYGWIN | ||
| 565 | if (bss_sbrk_did_unexec) | ||
| 566 | /* we're reinitializing the dumped emacs */ | ||
| 567 | { | ||
| 568 | bss_sbrk_heapbase = _heapbase; | ||
| 569 | bss_sbrk_heapinfo = _heapinfo; | ||
| 570 | memset (_fraghead, 0, BLOCKLOG * sizeof (struct list)); | ||
| 571 | } | ||
| 572 | #endif | ||
| 573 | |||
| 574 | if (__malloc_initialize_hook) | 576 | if (__malloc_initialize_hook) |
| 575 | (*__malloc_initialize_hook) (); | 577 | (*__malloc_initialize_hook) (); |
| 576 | 578 | ||
| @@ -1027,12 +1029,6 @@ _free_internal_nolock (void *ptr) | |||
| 1027 | if (ptr == NULL) | 1029 | if (ptr == NULL) |
| 1028 | return; | 1030 | return; |
| 1029 | 1031 | ||
| 1030 | #ifdef CYGWIN | ||
| 1031 | if ((char *) ptr < _heapbase) | ||
| 1032 | /* We're being asked to free something in the static heap. */ | ||
| 1033 | return; | ||
| 1034 | #endif | ||
| 1035 | |||
| 1036 | PROTECT_MALLOC_STATE (0); | 1032 | PROTECT_MALLOC_STATE (0); |
| 1037 | 1033 | ||
| 1038 | LOCK_ALIGNED_BLOCKS (); | 1034 | LOCK_ALIGNED_BLOCKS (); |
| @@ -1317,29 +1313,6 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. | |||
| 1317 | #define min(A, B) ((A) < (B) ? (A) : (B)) | 1313 | #define min(A, B) ((A) < (B) ? (A) : (B)) |
| 1318 | #endif | 1314 | #endif |
| 1319 | 1315 | ||
| 1320 | /* On Cygwin the dumped emacs may try to realloc storage allocated in | ||
| 1321 | the static heap. We just malloc space in the new heap and copy the | ||
| 1322 | data. */ | ||
| 1323 | #ifdef CYGWIN | ||
| 1324 | void * | ||
| 1325 | special_realloc (void *ptr, size_t size) | ||
| 1326 | { | ||
| 1327 | void *result; | ||
| 1328 | int type; | ||
| 1329 | size_t block, oldsize; | ||
| 1330 | |||
| 1331 | block = ((char *) ptr - bss_sbrk_heapbase) / BLOCKSIZE + 1; | ||
| 1332 | type = bss_sbrk_heapinfo[block].busy.type; | ||
| 1333 | oldsize = | ||
| 1334 | type == 0 ? bss_sbrk_heapinfo[block].busy.info.size * BLOCKSIZE | ||
| 1335 | : (size_t) 1 << type; | ||
| 1336 | result = _malloc_internal_nolock (size); | ||
| 1337 | if (result) | ||
| 1338 | return memcpy (result, ptr, min (oldsize, size)); | ||
| 1339 | return result; | ||
| 1340 | } | ||
| 1341 | #endif | ||
| 1342 | |||
| 1343 | /* Debugging hook for realloc. */ | 1316 | /* Debugging hook for realloc. */ |
| 1344 | void *(*__realloc_hook) (void *ptr, size_t size); | 1317 | void *(*__realloc_hook) (void *ptr, size_t size); |
| 1345 | 1318 | ||
| @@ -1364,12 +1337,6 @@ _realloc_internal_nolock (void *ptr, size_t size) | |||
| 1364 | else if (ptr == NULL) | 1337 | else if (ptr == NULL) |
| 1365 | return _malloc_internal_nolock (size); | 1338 | return _malloc_internal_nolock (size); |
| 1366 | 1339 | ||
| 1367 | #ifdef CYGWIN | ||
| 1368 | if ((char *) ptr < _heapbase) | ||
| 1369 | /* ptr points into the static heap */ | ||
| 1370 | return special_realloc (ptr, size); | ||
| 1371 | #endif | ||
| 1372 | |||
| 1373 | block = BLOCK (ptr); | 1340 | block = BLOCK (ptr); |
| 1374 | 1341 | ||
| 1375 | PROTECT_MALLOC_STATE (0); | 1342 | PROTECT_MALLOC_STATE (0); |
| @@ -1566,7 +1533,7 @@ __default_morecore (ptrdiff_t increment) | |||
| 1566 | { | 1533 | { |
| 1567 | void *result; | 1534 | void *result; |
| 1568 | #if defined (CYGWIN) | 1535 | #if defined (CYGWIN) |
| 1569 | if (!bss_sbrk_did_unexec) | 1536 | if (!DUMPED) |
| 1570 | { | 1537 | { |
| 1571 | return bss_sbrk (increment); | 1538 | return bss_sbrk (increment); |
| 1572 | } | 1539 | } |
| @@ -1689,6 +1656,9 @@ memalign (size_t alignment, size_t size) | |||
| 1689 | return aligned_alloc (alignment, size); | 1656 | return aligned_alloc (alignment, size); |
| 1690 | } | 1657 | } |
| 1691 | 1658 | ||
| 1659 | /* If HYBRID_MALLOC is defined, we may want to use the system | ||
| 1660 | posix_memalign below. */ | ||
| 1661 | #ifndef HYBRID_MALLOC | ||
| 1692 | int | 1662 | int |
| 1693 | posix_memalign (void **memptr, size_t alignment, size_t size) | 1663 | posix_memalign (void **memptr, size_t alignment, size_t size) |
| 1694 | { | 1664 | { |
| @@ -1707,6 +1677,7 @@ posix_memalign (void **memptr, size_t alignment, size_t size) | |||
| 1707 | 1677 | ||
| 1708 | return 0; | 1678 | return 0; |
| 1709 | } | 1679 | } |
| 1680 | #endif | ||
| 1710 | 1681 | ||
| 1711 | /* Allocate memory on a page boundary. | 1682 | /* Allocate memory on a page boundary. |
| 1712 | Copyright (C) 1991, 92, 93, 94, 96 Free Software Foundation, Inc. | 1683 | Copyright (C) 1991, 92, 93, 94, 96 Free Software Foundation, Inc. |
| @@ -1747,6 +1718,102 @@ valloc (size_t size) | |||
| 1747 | return aligned_alloc (pagesize, size); | 1718 | return aligned_alloc (pagesize, size); |
| 1748 | } | 1719 | } |
| 1749 | 1720 | ||
| 1721 | #ifdef HYBRID_MALLOC | ||
| 1722 | #undef malloc | ||
| 1723 | #undef realloc | ||
| 1724 | #undef calloc | ||
| 1725 | #undef aligned_alloc | ||
| 1726 | #undef free | ||
| 1727 | |||
| 1728 | /* See the comments near the beginning of this file for explanations | ||
| 1729 | of the following functions. */ | ||
| 1730 | |||
| 1731 | void * | ||
| 1732 | hybrid_malloc (size_t size) | ||
| 1733 | { | ||
| 1734 | if (DUMPED) | ||
| 1735 | return malloc (size); | ||
| 1736 | return gmalloc (size); | ||
| 1737 | } | ||
| 1738 | |||
| 1739 | void * | ||
| 1740 | hybrid_calloc (size_t nmemb, size_t size) | ||
| 1741 | { | ||
| 1742 | if (DUMPED) | ||
| 1743 | return calloc (nmemb, size); | ||
| 1744 | return gcalloc (nmemb, size); | ||
| 1745 | } | ||
| 1746 | |||
| 1747 | void | ||
| 1748 | hybrid_free (void *ptr) | ||
| 1749 | { | ||
| 1750 | if (!DUMPED) | ||
| 1751 | gfree (ptr); | ||
| 1752 | else if (!ALLOCATED_BEFORE_DUMPING (ptr)) | ||
| 1753 | free (ptr); | ||
| 1754 | /* Otherwise the dumped emacs is trying to free something allocated | ||
| 1755 | before dumping; do nothing. */ | ||
| 1756 | return; | ||
| 1757 | } | ||
| 1758 | |||
| 1759 | #if defined HAVE_ALIGNED_ALLOC || defined HAVE_POSIX_MEMALIGN | ||
| 1760 | void * | ||
| 1761 | hybrid_aligned_alloc (size_t alignment, size_t size) | ||
| 1762 | { | ||
| 1763 | if (!DUMPED) | ||
| 1764 | return galigned_alloc (alignment, size); | ||
| 1765 | /* The following is copied from alloc.c */ | ||
| 1766 | #ifdef HAVE_ALIGNED_ALLOC | ||
| 1767 | return aligned_alloc (alignment, size); | ||
| 1768 | #else /* HAVE_POSIX_MEMALIGN */ | ||
| 1769 | void *p; | ||
| 1770 | return posix_memalign (&p, alignment, size) == 0 ? p : 0; | ||
| 1771 | #endif | ||
| 1772 | } | ||
| 1773 | #endif | ||
| 1774 | |||
| 1775 | void * | ||
| 1776 | hybrid_realloc (void *ptr, size_t size) | ||
| 1777 | { | ||
| 1778 | void *result; | ||
| 1779 | int type; | ||
| 1780 | size_t block, oldsize; | ||
| 1781 | |||
| 1782 | if (!DUMPED) | ||
| 1783 | return grealloc (ptr, size); | ||
| 1784 | if (!ALLOCATED_BEFORE_DUMPING (ptr)) | ||
| 1785 | return realloc (ptr, size); | ||
| 1786 | |||
| 1787 | /* The dumped emacs is trying to realloc storage allocated before | ||
| 1788 | dumping. We just malloc new space and copy the data. */ | ||
| 1789 | if (size == 0 || ptr == NULL) | ||
| 1790 | return malloc (size); | ||
| 1791 | block = ((char *) ptr - _heapbase) / BLOCKSIZE + 1; | ||
| 1792 | type = _heapinfo[block].busy.type; | ||
| 1793 | oldsize = | ||
| 1794 | type == 0 ? _heapinfo[block].busy.info.size * BLOCKSIZE | ||
| 1795 | : (size_t) 1 << type; | ||
| 1796 | result = malloc (size); | ||
| 1797 | if (result) | ||
| 1798 | return memcpy (result, ptr, min (oldsize, size)); | ||
| 1799 | return result; | ||
| 1800 | } | ||
| 1801 | |||
| 1802 | #ifdef HYBRID_GET_CURRENT_DIR_NAME | ||
| 1803 | /* Defined in sysdep.c. */ | ||
| 1804 | char *gget_current_dir_name (void); | ||
| 1805 | |||
| 1806 | char * | ||
| 1807 | hybrid_get_current_dir_name (void) | ||
| 1808 | { | ||
| 1809 | if (DUMPED) | ||
| 1810 | return get_current_dir_name (); | ||
| 1811 | return gget_current_dir_name (); | ||
| 1812 | } | ||
| 1813 | #endif | ||
| 1814 | |||
| 1815 | #endif /* HYBRID_MALLOC */ | ||
| 1816 | |||
| 1750 | #ifdef GC_MCHECK | 1817 | #ifdef GC_MCHECK |
| 1751 | 1818 | ||
| 1752 | /* Standard debugging hooks for `malloc'. | 1819 | /* Standard debugging hooks for `malloc'. |