[Python-Dev] PyMem_Realloc corner case
Tim Peters
tim.one@comcast.net
Fri, 01 Mar 2002 02:27:25 -0500
[Jason Orendorff]
> I just got bit by the following:
>
> On Windows,
Which flavor of Windows? Which compiler? Which version of Python?
> PyMem_Realloc() doesn't seem to work as advertised in
> http://www.python.org/doc/current/api/memoryInterface.html
>
> In particular, "if n is equal to zero, the memory block is
> resized but is not freed, and the returned pointer is non-NULL".
I expect Fred made that up <wink>. Whatever, it isn't true on all
platforms.
> In Objects/object.c, lines 1878-1896, PyMem_Malloc() and
> PyMem_Realloc() seem to try to guarantee this behavior.
> Somehow it isn't working for me.
What does "isn't working" mean? What were your inputs and what was your
output? What did you expect instead?
> Does this mean MALLOC_ZERO_RETURNS_NULL should be defined
> in PC/pyconfig.h? Or do I have an off version of the CRT
> that causes problems nobody else has <sigh>?
Probably no and no: realloc'ing to 0 bytes is stupid, so I'd rather you
stopped hitting yourself over the head and that Python stopped encouraging
you to do so <wink>. You have control over one of those, anyway.
MS malloc(0) does not return NULL, which is why MALLOC_ZERO_RETURNS_NULL
should not be #define'd. However, MS realloc(p, 0) returns NULL if and only
if p is not NULL (well, MS realloc(NULL, 0) can return NULL if there's not
enough heap space remaining to allocate a dummy object), and if p is not
NULL does free the block. All of this is fine by the C standard.
If people think this needs to "be fixed", fine, but I woould strongly oppose
#define'ing MALLOC_ZERO_RETURNS_NULL on Windows: adding the silly 1 to all
malloc calls then can cause overallocation by 8 bytes, that's a horrible
waste, and whoever assumed malloc(0) behavior was correlated with
realloc(not-NULL, 0) behavior to begin with was wrong. Better to get rid of
MALLOC_ZERO_RETURNS_NULL, and get rid of _PyMem_EXTRA, instead
special-casing the snot out of a 0 argumentl e.g. instead of
void *
PyMem_Realloc(void *p, size_t nbytes)
{
#if _PyMem_EXTRA > 0
if (nbytes == 0)
nbytes = _PyMem_EXTRA;
#endif
return PyMem_REALLOC(p, nbytes);
}
do
void *
PyMem_Realloc(void *p, size_t nbytes)
{
return PyMem_REALLOC(p, nbytes ? nbytes : 1);
}
instead.
Note: The pymalloc realloc works just like the MS realloc here, so it's not
"just Windows"; from obmalloc.c's _THIS_REALLOC:
/* Don't bother if a smaller size was requested
except for realloc(p, 0) == free(p), ret NULL */
if (nbytes == 0) {
_THIS_FREE(p);
bp = NULL;
In fact, I believe it's *common* for realloc(not-NULL, 0) to act like
free(not-NULL), and that's allowed but not required by C. The overly gross
MALLOC_ZERO_RETURNS_NULL is thus likely not defined on lots of platforms
with this realloc behavior.
Can we call it a doc error?