@@ -1926,6 +1926,10 @@ _Py_GetAllocatedBlocks(void)
19261926#define DEADBYTE 0xDD /* dead (newly freed) memory */
19271927#define FORBIDDENBYTE 0xFD /* untouchable bytes at each end of a block */
19281928
1929+ /* Uncomment this define to add the "serialno" field */
1930+ /* #define PYMEM_DEBUG_SERIALNO */
1931+
1932+ #ifdef PYMEM_DEBUG_SERIALNO
19291933static size_t serialno = 0 ; /* incremented on each debug {m,re}alloc */
19301934
19311935/* serialno is always incremented via calling this routine. The point is
@@ -1936,9 +1940,16 @@ bumpserialno(void)
19361940{
19371941 ++ serialno ;
19381942}
1943+ #endif
19391944
19401945#define SST SIZEOF_SIZE_T
19411946
1947+ #ifdef PYMEM_DEBUG_SERIALNO
1948+ # define PYMEM_DEBUG_EXTRA_BYTES 4 * SST
1949+ #else
1950+ # define PYMEM_DEBUG_EXTRA_BYTES 3 * SST
1951+ #endif
1952+
19421953/* Read sizeof(size_t) bytes at p as a big-endian size_t. */
19431954static size_t
19441955read_size_t (const void * p )
@@ -1967,7 +1978,7 @@ write_size_t(void *p, size_t n)
19671978 }
19681979}
19691980
1970- /* Let S = sizeof(size_t). The debug malloc asks for 4* S extra bytes and
1981+ /* Let S = sizeof(size_t). The debug malloc asks for 4 * S extra bytes and
19711982 fills them with useful stuff, here calling the underlying malloc's result p:
19721983
19731984p[0: S]
@@ -1991,6 +2002,9 @@ p[2*S+n+S: 2*S+n+2*S]
19912002 If "bad memory" is detected later, the serial number gives an
19922003 excellent way to set a breakpoint on the next run, to capture the
19932004 instant at which this block was passed out.
2005+
2006+ If PYMEM_DEBUG_SERIALNO is not defined (default), the debug malloc only asks
2007+ for 3 * S extra bytes, and omits the last serialno field.
19942008*/
19952009
19962010static void *
@@ -2000,21 +2014,24 @@ _PyMem_DebugRawAlloc(int use_calloc, void *ctx, size_t nbytes)
20002014 uint8_t * p ; /* base address of malloc'ed pad block */
20012015 uint8_t * data ; /* p + 2*SST == pointer to data bytes */
20022016 uint8_t * tail ; /* data + nbytes == pointer to tail pad bytes */
2003- size_t total ; /* 2 * SST + nbytes + 2 * SST */
2017+ size_t total ; /* nbytes + PYMEM_DEBUG_EXTRA_BYTES */
20042018
2005- if (nbytes > (size_t )PY_SSIZE_T_MAX - 4 * SST ) {
2019+ if (nbytes > (size_t )PY_SSIZE_T_MAX - PYMEM_DEBUG_EXTRA_BYTES ) {
20062020 /* integer overflow: can't represent total as a Py_ssize_t */
20072021 return NULL ;
20082022 }
2009- total = nbytes + 4 * SST ;
2023+ total = nbytes + PYMEM_DEBUG_EXTRA_BYTES ;
20102024
20112025 /* Layout: [SSSS IFFF CCCC...CCCC FFFF NNNN]
2012- * ^--- p ^--- data ^--- tail
2026+ ^--- p ^--- data ^--- tail
20132027 S: nbytes stored as size_t
20142028 I: API identifier (1 byte)
20152029 F: Forbidden bytes (size_t - 1 bytes before, size_t bytes after)
20162030 C: Clean bytes used later to store actual data
2017- N: Serial number stored as size_t */
2031+ N: Serial number stored as size_t
2032+
2033+ If PYMEM_DEBUG_SERIALNO is not defined (default), the last NNNN field
2034+ is omitted. */
20182035
20192036 if (use_calloc ) {
20202037 p = (uint8_t * )api -> alloc .calloc (api -> alloc .ctx , 1 , total );
@@ -2027,7 +2044,9 @@ _PyMem_DebugRawAlloc(int use_calloc, void *ctx, size_t nbytes)
20272044 }
20282045 data = p + 2 * SST ;
20292046
2047+ #ifdef PYMEM_DEBUG_SERIALNO
20302048 bumpserialno ();
2049+ #endif
20312050
20322051 /* at p, write size (SST bytes), id (1 byte), pad (SST-1 bytes) */
20332052 write_size_t (p , nbytes );
@@ -2041,7 +2060,9 @@ _PyMem_DebugRawAlloc(int use_calloc, void *ctx, size_t nbytes)
20412060 /* at tail, write pad (SST bytes) and serialno (SST bytes) */
20422061 tail = data + nbytes ;
20432062 memset (tail , FORBIDDENBYTE , SST );
2063+ #ifdef PYMEM_DEBUG_SERIALNO
20442064 write_size_t (tail + SST , serialno );
2065+ #endif
20452066
20462067 return data ;
20472068}
@@ -2081,7 +2102,7 @@ _PyMem_DebugRawFree(void *ctx, void *p)
20812102
20822103 _PyMem_DebugCheckAddress (api -> api_id , p );
20832104 nbytes = read_size_t (q );
2084- nbytes += 4 * SST ;
2105+ nbytes += PYMEM_DEBUG_EXTRA_BYTES ;
20852106 memset (q , DEADBYTE , nbytes );
20862107 api -> alloc .free (api -> alloc .ctx , q );
20872108}
@@ -2101,7 +2122,6 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
21012122 uint8_t * tail ; /* data + nbytes == pointer to tail pad bytes */
21022123 size_t total ; /* 2 * SST + nbytes + 2 * SST */
21032124 size_t original_nbytes ;
2104- size_t block_serialno ;
21052125#define ERASED_SIZE 64
21062126 uint8_t save [2 * ERASED_SIZE ]; /* A copy of erased bytes. */
21072127
@@ -2110,47 +2130,57 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
21102130 data = (uint8_t * )p ;
21112131 head = data - 2 * SST ;
21122132 original_nbytes = read_size_t (head );
2113- if (nbytes > (size_t )PY_SSIZE_T_MAX - 4 * SST ) {
2133+ if (nbytes > (size_t )PY_SSIZE_T_MAX - PYMEM_DEBUG_EXTRA_BYTES ) {
21142134 /* integer overflow: can't represent total as a Py_ssize_t */
21152135 return NULL ;
21162136 }
2117- total = nbytes + 4 * SST ;
2137+ total = nbytes + PYMEM_DEBUG_EXTRA_BYTES ;
21182138
21192139 tail = data + original_nbytes ;
2120- block_serialno = read_size_t (tail + SST );
2140+ #ifdef PYMEM_DEBUG_SERIALNO
2141+ size_t block_serialno = read_size_t (tail + SST );
2142+ #endif
21212143 /* Mark the header, the trailer, ERASED_SIZE bytes at the begin and
21222144 ERASED_SIZE bytes at the end as dead and save the copy of erased bytes.
21232145 */
21242146 if (original_nbytes <= sizeof (save )) {
21252147 memcpy (save , data , original_nbytes );
2126- memset (data - 2 * SST , DEADBYTE , original_nbytes + 4 * SST );
2148+ memset (data - 2 * SST , DEADBYTE ,
2149+ original_nbytes + PYMEM_DEBUG_EXTRA_BYTES );
21272150 }
21282151 else {
21292152 memcpy (save , data , ERASED_SIZE );
2130- memset (head , DEADBYTE , ERASED_SIZE + 2 * SST );
2153+ memset (head , DEADBYTE , ERASED_SIZE + 2 * SST );
21312154 memcpy (& save [ERASED_SIZE ], tail - ERASED_SIZE , ERASED_SIZE );
2132- memset (tail - ERASED_SIZE , DEADBYTE , ERASED_SIZE + 2 * SST );
2155+ memset (tail - ERASED_SIZE , DEADBYTE ,
2156+ ERASED_SIZE + PYMEM_DEBUG_EXTRA_BYTES - 2 * SST );
21332157 }
21342158
21352159 /* Resize and add decorations. */
21362160 r = (uint8_t * )api -> alloc .realloc (api -> alloc .ctx , head , total );
21372161 if (r == NULL ) {
2162+ /* if realloc() failed: rewrite header and footer which have
2163+ just been erased */
21382164 nbytes = original_nbytes ;
21392165 }
21402166 else {
21412167 head = r ;
2168+ #ifdef PYMEM_DEBUG_SERIALNO
21422169 bumpserialno ();
21432170 block_serialno = serialno ;
2171+ #endif
21442172 }
2173+ data = head + 2 * SST ;
21452174
21462175 write_size_t (head , nbytes );
21472176 head [SST ] = (uint8_t )api -> api_id ;
21482177 memset (head + SST + 1 , FORBIDDENBYTE , SST - 1 );
2149- data = head + 2 * SST ;
21502178
21512179 tail = data + nbytes ;
21522180 memset (tail , FORBIDDENBYTE , SST );
2181+ #ifdef PYMEM_DEBUG_SERIALNO
21532182 write_size_t (tail + SST , block_serialno );
2183+ #endif
21542184
21552185 /* Restore saved bytes. */
21562186 if (original_nbytes <= sizeof (save )) {
@@ -2170,7 +2200,7 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
21702200 }
21712201
21722202 if (nbytes > original_nbytes ) {
2173- /* growing: mark new extra memory clean */
2203+ /* growing: mark new extra memory clean */
21742204 memset (data + original_nbytes , CLEANBYTE , nbytes - original_nbytes );
21752205 }
21762206
@@ -2278,7 +2308,7 @@ _PyObject_DebugDumpAddress(const void *p)
22782308{
22792309 const uint8_t * q = (const uint8_t * )p ;
22802310 const uint8_t * tail ;
2281- size_t nbytes , serial ;
2311+ size_t nbytes ;
22822312 int i ;
22832313 int ok ;
22842314 char id ;
@@ -2347,9 +2377,11 @@ _PyObject_DebugDumpAddress(const void *p)
23472377 }
23482378 }
23492379
2350- serial = read_size_t (tail + SST );
2380+ #ifdef PYMEM_DEBUG_SERIALNO
2381+ size_t serial = read_size_t (tail + SST );
23512382 fprintf (stderr , " The block was made by call #%" PY_FORMAT_SIZE_T
23522383 "u to debug malloc/realloc.\n" , serial );
2384+ #endif
23532385
23542386 if (nbytes > 0 ) {
23552387 i = 0 ;
@@ -2575,8 +2607,11 @@ _PyObject_DebugMallocStats(FILE *out)
25752607 quantization += p * ((POOL_SIZE - POOL_OVERHEAD ) % size );
25762608 }
25772609 fputc ('\n' , out );
2578- if (_PyMem_DebugEnabled ())
2610+ #ifdef PYMEM_DEBUG_SERIALNO
2611+ if (_PyMem_DebugEnabled ()) {
25792612 (void )printone (out , "# times object malloc called" , serialno );
2613+ }
2614+ #endif
25802615 (void )printone (out , "# arenas allocated total" , ntimes_arena_allocated );
25812616 (void )printone (out , "# arenas reclaimed" , ntimes_arena_allocated - narenas );
25822617 (void )printone (out , "# arenas highwater mark" , narenas_highwater );
0 commit comments