Mailing List Archive

python/dist/src/Objects obmalloc.c,2.37,2.38
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv28856/python/Objects

Modified Files:
obmalloc.c
Log Message:
_PyObject_DebugRealloc(): rewritten to let the underlying realloc do
most of the work. In particular, if the underlying realloc is able to
grow the memory block in place, great (this routine used to do a fresh
malloc + memcpy every time a block grew). BTW, I'm not so keen here on
avoiding possible quadratic-time realloc patterns as I am on making
the debug pymalloc more invisible (the more it uses memory "just like"
the underlying allocator, the better the chance that a suspected memory
corruption bug won't vanish when the debug malloc is turned on).


Index: obmalloc.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/obmalloc.c,v
retrieving revision 2.37
retrieving revision 2.38
diff -C2 -d -r2.37 -r2.38
*** obmalloc.c 12 Apr 2002 07:43:07 -0000 2.37
--- obmalloc.c 12 Apr 2002 08:52:50 -0000 2.38
***************
*** 1006,1011 ****
{
uchar *q = (uchar *)p;
size_t original_nbytes;
- void *fresh; /* new memory block, if needed */

if (p == NULL)
--- 1006,1012 ----
{
uchar *q = (uchar *)p;
+ uchar *tail;
+ size_t total; /* nbytes + 16 */
size_t original_nbytes;

if (p == NULL)
***************
*** 1013,1049 ****

_PyObject_DebugCheckAddress(p);
original_nbytes = read4(q-8);
! if (nbytes == original_nbytes) {
! /* note that this case is likely to be common due to the
! way Python appends to lists */
! bumpserialno();
! write4(q + nbytes + 4, serialno);
! return p;
}

if (nbytes < original_nbytes) {
! /* shrinking -- leave the guts alone, except to
! fill the excess with DEADBYTE */
! const size_t excess = original_nbytes - nbytes;
! bumpserialno();
! write4(q-8, nbytes);
! /* kill the excess bytes plus the trailing 8 pad bytes */
! q += nbytes;
! q[0] = q[1] = q[2] = q[3] = FORBIDDENBYTE;
! write4(q+4, serialno);
! memset(q+8, DEADBYTE, excess);
! 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 = _PyObject_DebugMalloc(nbytes);
! if (fresh != NULL) {
! if (original_nbytes > 0)
! memcpy(fresh, p, original_nbytes);
! _PyObject_DebugFree(p);
}
! return fresh;
}

--- 1014,1052 ----

_PyObject_DebugCheckAddress(p);
+ bumpserialno();
original_nbytes = read4(q-8);
! total = nbytes + 16;
! if (total < nbytes || (total >> 31) > 1) {
! /* overflow, or we can't represent it in 4 bytes */
! return NULL;
}

if (nbytes < original_nbytes) {
! /* shrinking: mark old extra memory dead */
! memset(q + nbytes, DEADBYTE, original_nbytes - nbytes);
}

! /* Resize and add decorations. */
! q = (uchar *)PyObject_Realloc(q-8, total);
! if (q == NULL)
! return NULL;
!
! write4(q, nbytes);
! assert(q[4] == FORBIDDENBYTE &&
! q[5] == FORBIDDENBYTE &&
! q[6] == FORBIDDENBYTE &&
! q[7] == FORBIDDENBYTE);
! q += 8;
! tail = q + nbytes;
! tail[0] = tail[1] = tail[2] = tail[3] = FORBIDDENBYTE;
! write4(tail + 4, serialno);
!
! if (nbytes > original_nbytes) {
! /* growing: mark new extra memory clean */
! memset(q + original_nbytes, CLEANBYTE,
! nbytes - original_nbytes);
}
!
! return q;
}