This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/12547] realloc(p, 0) violates C99


http://sourceware.org/bugzilla/show_bug.cgi?id=12547

Eric Blake <eblake at redhat dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|WONTFIX                     |

--- Comment #7 from Eric Blake <eblake at redhat dot com> 2011-04-01 22:51:34 UTC ---
We can't just blindly ignore the WG14 C committee - either we have to fight
them harder to get the C1x standard (now in draft balloting) fixed, or we'll
have to give in and implement something like __xpg_realloc :(

Would anyone be willing to implement a systemtap probe to find out how many
programs in real life actually use realloc(p,0) in the first place, to see the
extent of the damage control if we are forced to change semantics?



Sent to the SC22WG14 email reflector:

The Austin Group has been studying this problem (see
http://austingroupbugs.net/view.php?id=400) [^] and trying to resolve any
conflict with C. This was also examined by WG14 during the London meeting,
where the resolution was "POSIX should conform to the requirements of C". The
Austin Group agrees with this resolution.

However, during our discussions, we have found the following in the C standard
(using refs to C99, not C1x):

Point 1: Objects cannot be zero sized.
6.2.6.1(2) Except for bit-fields, objects are composed of contiguous sequences
of one or more bytes,

Point 2: realloc(NULL, 0) is required to behave like malloc(0), and malloc
states "7.20.3.3(2) The malloc function allocates space for an object whose
size is specified by size and whose value is indeterminate." Since objects
cannot be zero sized, returning a non-null pointer is at best questionable.
However, this argues that realloc(p, 0) should always fail.

Point 3: Explicit permission to succeed AND return NULL is granted: "7.20.3(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 returned pointer shall not be used to
access an object." [this refers to calloc, malloc and realloc]. It has been
claimed that if realloc(p,0) returns a null pointer, that indicates that "the
new object cannot be allocated" and so the old object remains alive. However,
that interpretation is not clear, and the two separate sentences in 7.20.3.1
about null pointers are distinct cases, and the second does not necessarily
imply the first.

The POSIX words currently follow the original C89 text, and not the C99 update.
They state: "If size is 0 and ptr is not a null pointer,
the object pointed to is freed. ...RETURNS... If size is 0, either a null
pointer or a unique pointer that can be successfully passed to free() shall be
returned." The C99 words state "7.20.3.4(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." This would appear to allow an implementation to
deallocate the space and then return NULL (without setting errno).
Additionally, "7.20.3(3) ... or if the space has been deallocated by a call to
the free or realloc function..." strongly suggests that realloc(ptr, 0) is a
valid way to free ptr.

So, the Austin Group currently does not believe that POSIX conflicts with C,
and that it is permissible for realloc(p, 0) (where p is non-NULL) to free the
space allocated and return NULL. In POSIX, it is acceptable to set errno to
zero before the call, and test it afterwards to see if the pointer has been
freed or not.

Our current survey has shown that the following implementations free the
pointer and return NULL :

Glibc (GNU/Linux)
AIX
HP-UX
Solaris
OSF/1

There is strong resistance from at least one of these to changing their
implementation, in the belief that this would make current, memory leak free,
conforming code become both non-conforming and leaking.

-- 
Nick Stoughton
Austin Group/WG14 Liaison


    Reply on SC22WG14 reflector:

What WG 14 has been saying is that that interpretation is
incorrect. Referencing the latest C1x draft:

1. 7.22.3.5p4, "Returns," states "The realloc function returns a
pointer to the new object (which may have the same value as a pointer to
the old object), or a null pointer if the new object could not be
allocated." In other words, null means failure.

2. 7.22.3p1 states "If the space cannot be allocated, a null pointer is
returned. 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
returned pointer shall not be used to access an object." This, together
with the previous quote, means that the function can either succeed and
return a valid pointer, or fail and return a null pointer.

3. 7.22.3.5p1 states "If memory for the new object cannot be allocated,
the old object is not deallocated and its value is unchanged." This,
together with the previous two quotes, means that if a null pointer is
returned, the operation has failed and the old object is not deallocated.

      You mentioned the fact that objects cannot be zero sized. That is
why the wording is the way it is. If we had zero-sized objects, we
could just say that an allocation of size zero returns a pointer to just
past the end of a zero-sized object (and that is why the pointer cannot
be dereferenced). Instead, we have to say the same thing without
talking about zero-sized objects.

-- 
Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]