[Python-Dev] PyMem_Realloc corner case
Jason Orendorff
jason@jorendorff.com
Thu, 14 Mar 2002 11:54:57 -0600
Tim Peters wrote:
> [Jason Orendorff]
> > I just got bit by the following:
> >
> > On Windows,
>
> Which flavor of Windows? Which compiler? Which version of Python?
Ah! I just got this message. You correctly divined the cause of
my problems without all this information, so I'll cut to the chase:
> [...] realloc'ing to 0 bytes is stupid [...]
Enough said.
I will indulge in a little whining though (below).
> 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.
> [...]
> 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.
Well... here's what the standard says:
| 7.20.3 Memory management functions
| 1 [...]
| If the size of the space requested is zero, the behavior is
| implementation-defined: either a null pointer is returned, or the
| behavior is as if the size were some nonzero value, except that the
| pointer returned shall not be used to access an object.
This applies to calloc, malloc, and realloc. And:
| 7.20.3.4 The realloc function
| Synopsis
| #include <stdlib.h>
| void *realloc(void *ptr, size_t size);
| Description
| 2 The realloc function deallocates the old object pointed to
| by ptr and returns a pointer to a new object that has the size
| specified by size. The contents of the new object shall be the
| same as that of the old object prior to deallocation, up to the
| lesser of the new and old sizes.
If you set knowing how Microsoft's realloc() or PyMalloc's
realloc() works, you could read the standard to allow them.
But a casual reading suggests
(a) "the behavior is implementation-defined: either X or Y"
- a given implementation must pick one or the other, not
switch back and forth for different cases.
(b) "deallocates the old object...returns a pointer to a new
object" - should behave like a free/malloc combo. That is,
y=realloc(x, 0); should behave like free(x); y=malloc(0);
Anyway, I'm sure you've had enough of me by now, so I'll stop. :)
## Jason Orendorff http://www.jorendorff.com/