summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2002-04-11 06:36:45 (GMT)
committerTim Peters <tim.peters@gmail.com>2002-04-11 06:36:45 (GMT)
commit52aefc8a7b9e9ebda6c1b98a831a273e0b07bf96 (patch)
tree464e320ea0de3e2604b99ddc6fcaa8e965ce3124
parent362ed3451e1f95bcc327f4ed0f484d37363bfe5f (diff)
downloadcpython-52aefc8a7b9e9ebda6c1b98a831a273e0b07bf96.zip
cpython-52aefc8a7b9e9ebda6c1b98a831a273e0b07bf96.tar.gz
cpython-52aefc8a7b9e9ebda6c1b98a831a273e0b07bf96.tar.bz2
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).
-rw-r--r--Objects/obmalloc.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c
index fba03ea..cfcff2c 100644
--- a/Objects/obmalloc.c
+++ b/Objects/obmalloc.c
@@ -321,13 +321,14 @@ pymalloc strives at all levels (arena, pool, and block) never to touch a piece
of memory until it's actually needed.
So long as a pool is in the used state, we're certain there *is* a block
-available for allocating. If pool->freeblock is NULL then, that means we
-simply haven't yet gotten to one of the higher-address blocks. The offset
-from the pool_header to the start of "the next" virgin block is stored in
-the pool_header nextoffset member, and the largest value of nextoffset that
-makes sense is stored in the maxnextoffset member when a pool is initialized.
-All the blocks in a pool have been passed out at least once when and only
-when nextoffset > maxnextoffset.
+available for allocating, and pool->freeblock is not NULL. If pool->freeblock
+points to the end of the free list before we've carved the entire pool into
+blocks, that means we simply haven't yet gotten to one of the higher-address
+blocks. The offset from the pool_header to the start of "the next" virgin
+block is stored in the pool_header nextoffset member, and the largest value
+of nextoffset that makes sense is stored in the maxnextoffset member when a
+pool is initialized. All the blocks in a pool have been passed out at least
+once when and only when nextoffset > maxnextoffset.
Major obscurity: While the usedpools vector is declared to have poolp
@@ -467,8 +468,7 @@ new_arena(void)
maxarenas = 16;
}
else if (narenas == maxarenas) {
- /* Grow arenas. Don't use realloc: if this fails, we
- * don't want to lose the base addresses we already have.
+ /* Grow arenas.
*
* Exceedingly subtle: Someone may be calling the pymalloc
* free via PyMem_{DEL, Del, FREE, Free} without holding the
@@ -590,6 +590,7 @@ _PyMalloc_Malloc(size_t nbytes)
*/
++pool->ref.count;
bp = pool->freeblock;
+ assert(bp != NULL);
if ((pool->freeblock = *(block **)bp) != NULL) {
UNLOCK();
return (void *)bp;
@@ -1057,12 +1058,15 @@ _PyMalloc_DebugRealloc(void *p, size_t nbytes)
return p;
}
+ assert(nbytes != 0);
/* More memory is needed: get it, copy over the first original_nbytes
of the original data, and free the original memory. */
fresh = _PyMalloc_DebugMalloc(nbytes);
- if (fresh != NULL && original_nbytes > 0)
- memcpy(fresh, p, original_nbytes);
- _PyMalloc_DebugFree(p);
+ if (fresh != NULL) {
+ if (original_nbytes > 0)
+ memcpy(fresh, p, original_nbytes);
+ _PyMalloc_DebugFree(p);
+ }
return fresh;
}