Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 52aefc8

Browse files
committed
SF bug 542181: Realloc behavior
The bug report pointed out a bogosity in the comment block explaining thread safety for arena management. Repaired that comment, repaired a couple others while I was at it, and added an assert. _PyMalloc_DebugRealloc: If this needed to get more memory, but couldn't, it erroneously freed the original memory. Repaired that. This is for 2.3 only (unless we decide to backport the new pymalloc).
1 parent 362ed34 commit 52aefc8

1 file changed

Lines changed: 16 additions & 12 deletions

File tree

Objects/obmalloc.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -321,13 +321,14 @@ pymalloc strives at all levels (arena, pool, and block) never to touch a piece
321321
of memory until it's actually needed.
322322
323323
So long as a pool is in the used state, we're certain there *is* a block
324-
available for allocating. If pool->freeblock is NULL then, that means we
325-
simply haven't yet gotten to one of the higher-address blocks. The offset
326-
from the pool_header to the start of "the next" virgin block is stored in
327-
the pool_header nextoffset member, and the largest value of nextoffset that
328-
makes sense is stored in the maxnextoffset member when a pool is initialized.
329-
All the blocks in a pool have been passed out at least once when and only
330-
when nextoffset > maxnextoffset.
324+
available for allocating, and pool->freeblock is not NULL. If pool->freeblock
325+
points to the end of the free list before we've carved the entire pool into
326+
blocks, that means we simply haven't yet gotten to one of the higher-address
327+
blocks. The offset from the pool_header to the start of "the next" virgin
328+
block is stored in the pool_header nextoffset member, and the largest value
329+
of nextoffset that makes sense is stored in the maxnextoffset member when a
330+
pool is initialized. All the blocks in a pool have been passed out at least
331+
once when and only when nextoffset > maxnextoffset.
331332
332333
333334
Major obscurity: While the usedpools vector is declared to have poolp
@@ -467,8 +468,7 @@ new_arena(void)
467468
maxarenas = 16;
468469
}
469470
else if (narenas == maxarenas) {
470-
/* Grow arenas. Don't use realloc: if this fails, we
471-
* don't want to lose the base addresses we already have.
471+
/* Grow arenas.
472472
*
473473
* Exceedingly subtle: Someone may be calling the pymalloc
474474
* free via PyMem_{DEL, Del, FREE, Free} without holding the
@@ -590,6 +590,7 @@ _PyMalloc_Malloc(size_t nbytes)
590590
*/
591591
++pool->ref.count;
592592
bp = pool->freeblock;
593+
assert(bp != NULL);
593594
if ((pool->freeblock = *(block **)bp) != NULL) {
594595
UNLOCK();
595596
return (void *)bp;
@@ -1057,12 +1058,15 @@ _PyMalloc_DebugRealloc(void *p, size_t nbytes)
10571058
return p;
10581059
}
10591060

1061+
assert(nbytes != 0);
10601062
/* More memory is needed: get it, copy over the first original_nbytes
10611063
of the original data, and free the original memory. */
10621064
fresh = _PyMalloc_DebugMalloc(nbytes);
1063-
if (fresh != NULL && original_nbytes > 0)
1064-
memcpy(fresh, p, original_nbytes);
1065-
_PyMalloc_DebugFree(p);
1065+
if (fresh != NULL) {
1066+
if (original_nbytes > 0)
1067+
memcpy(fresh, p, original_nbytes);
1068+
_PyMalloc_DebugFree(p);
1069+
}
10661070
return fresh;
10671071
}
10681072

0 commit comments

Comments
 (0)