By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,247 Members | 871 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,247 IT Pros & Developers. It's quick & easy.

realloc zero bytes?

P: n/a

The C standard doesn't say anything about what happens when you call
realloc with a size argument of 0. Both glibc and openbsd appear to
return a valid pointer to a zero-sized object.. e.g. the return of a
malloc(0).

Does anyone know of a runtime where realloc() free'ed the object and
then returned NULL? If so, it would make the following idiom for
realloc() exploitable. Here's the idiom, snagged from an openbsd man page:

if ((p2 = realloc(p, nsize)) == NULL) {
if (p)
free(p);
p = NULL;
return NULL;
}
p = p2;

You can see that if nsize is 0 and realloc() free'ed the memory and
returned NULL, it would be a double-free of p.

Thanks,
rCs
Jan 9 '07 #1
Share this Question
Share on Google+
64 Replies


P: n/a
Robert Seacord <rc*@sei.cmu.eduwrote:
>
The C standard doesn't say anything about what happens when you call
realloc with a size argument of 0. Both glibc and openbsd appear to
return a valid pointer to a zero-sized object.. e.g. the return of a
malloc(0).

Does anyone know of a runtime where realloc() free'ed the object and
then returned NULL? If so, it would make the following idiom for
realloc() exploitable. Here's the idiom, snagged from an openbsd man page:
The standard (C99) says:
7.20.3.4-3
"... If memory for the new object cannot be allocated, the old object is
not deallocated and its value is unchanged.".
Also:
7.20.3.4-4
"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."
if ((p2 = realloc(p, nsize)) == NULL) {
if (p)
free(p);
If realloc fails then p retains its old value. If p is NULL when you
pass it to realloc you already know it's NULL and you don't want to free
it.
p = NULL;
return NULL;
}
p = p2;

You can see that if nsize is 0 and realloc() free'ed the memory and
returned NULL, it would be a double-free of p.
Realloc won't free the memory and return NULL because the standard says
it doesn't.
--
Ioan - Ciprian Tandau
tandau _at_ freeshell _dot_ org (hope it's not too late)
(... and that it still works...)

Jan 9 '07 #2

P: n/a
Nelu wrote:
Robert Seacord <rc*@sei.cmu.eduwrote:
>>The C standard doesn't say anything about what happens when you call
realloc with a size argument of 0. Both glibc and openbsd appear to
return a valid pointer to a zero-sized object.. e.g. the return of a
malloc(0).

Does anyone know of a runtime where realloc() free'ed the object and
then returned NULL? If so, it would make the following idiom for
realloc() exploitable. Here's the idiom, snagged from an openbsd man page:


The standard (C99) says:
7.20.3.4-3
"... If memory for the new object cannot be allocated, the old object is
not deallocated and its value is unchanged.".
Also:
7.20.3.4-4
"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."
But if size is 0, there won't be any problems allocating he memory, so
nothing will be allocated and the existing memory will be freed.
>

Realloc won't free the memory and return NULL because the standard says
it doesn't.
Surely it may free the memory and return a pointer to a zero sized block.

--
Ian Collins.
Jan 9 '07 #3

P: n/a
Ian Collins <ia******@hotmail.comwrote:
Nelu wrote:
>Robert Seacord <rc*@sei.cmu.eduwrote:
>>>The C standard doesn't say anything about what happens when you call
realloc with a size argument of 0. Both glibc and openbsd appear to
return a valid pointer to a zero-sized object.. e.g. the return of a
malloc(0).

Does anyone know of a runtime where realloc() free'ed the object and
then returned NULL? If so, it would make the following idiom for
realloc() exploitable. Here's the idiom, snagged from an openbsd man page:


The standard (C99) says:
7.20.3.4-3
"... If memory for the new object cannot be allocated, the old object is
not deallocated and its value is unchanged.".
Also:
7.20.3.4-4
"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."
But if size is 0, there won't be any problems allocating he memory, so
nothing will be allocated and the existing memory will be freed.
And it will return a valid pointer that will not be NULL and p2==NULL
will be false.
>>

Realloc won't free the memory and return NULL because the standard says
it doesn't.
Surely it may free the memory and return a pointer to a zero sized block.
A valid pointer that's not NULL.

--
Ioan - Ciprian Tandau
tandau _at_ freeshell _dot_ org (hope it's not too late)
(... and that it still works...)

Jan 9 '07 #4

P: n/a
On Tue, 09 Jan 2007 15:43:48 -0500, Robert Seacord <rc*@sei.cmu.edu>
wrote:
>
The C standard doesn't say anything about what happens when you call
realloc with a size argument of 0. Both glibc and openbsd appear to
return a valid pointer to a zero-sized object.. e.g. the return of a
malloc(0).
Of course it does. In n1124 7.20.3, which discusses all three
allocation functions, it says "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.
>Does anyone know of a runtime where realloc() free'ed the object and
then returned NULL? If so, it would make the following idiom for
realloc() exploitable. Here's the idiom, snagged from an openbsd man page:

if ((p2 = realloc(p, nsize)) == NULL) {
if (p)
free(p);
p = NULL;
return NULL;
}
p = p2;

You can see that if nsize is 0 and realloc() free'ed the memory and
returned NULL, it would be a double-free of p.
If you add a test for nsize, you can make it safe regardless of the
return value.
Remove del for email
Jan 10 '07 #5

P: n/a
Barry Schwarz wrote:
>
On Tue, 09 Jan 2007 15:43:48 -0500, Robert Seacord <rc*@sei.cmu.edu>
wrote:

The C standard doesn't say anything about what happens when you call
realloc with a size argument of 0. Both glibc and openbsd appear to
return a valid pointer to a zero-sized object.. e.g. the return of a
malloc(0).

Of course it does. In n1124 7.20.3, which discusses all three
allocation functions, it says "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.
What happens on an implementation in which malloc(0) returns NULL,
and you pass realloc() zero for the length? Is realloc() allowed
to return NULL?

The source to the runtime library I have here has this note:
* Special ANSI Requirements:
*
* (1) realloc(NULL, newsize) is equivalent to malloc(newsize)
*
* (2) realloc(pblock, 0) is equivalent to free(pblock) (except that
* NULL is returned)
*
* (3) if the realloc() fails, the object pointed to by pblock is left
* unchanged
Is (2) correct? Does ANSI require that the block be free()d and
that NULL be returned?

[...]

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>
Jan 10 '07 #6

P: n/a
Kenneth Brody writes:
The source to the runtime library I have here has this note:
>* Special ANSI Requirements:
*
* (1) realloc(NULL, newsize) is equivalent to malloc(newsize)
Yes...
>* (2) realloc(pblock, 0) is equivalent to free(pblock) (except that
* NULL is returned)
C89 4.10.3.4 says "If size is zero and ptr is not a null pointer, the
object it points to is freed." The clause has been deleted from C99.
>* (3) if the realloc() fails, the object pointed to by pblock is left
* unchanged
Yes.

--
Regards,
Hallvard
Jan 10 '07 #7

P: n/a
Hallvard B Furuseth wrote:
>
Kenneth Brody writes:
The source to the runtime library I have here has this note:
* Special ANSI Requirements:
[...]
* (2) realloc(pblock, 0) is equivalent to free(pblock) (except that
* NULL is returned)

C89 4.10.3.4 says "If size is zero and ptr is not a null pointer, the
object it points to is freed." The clause has been deleted from C99.
But what about returning NULL? In all other cases, a NULL return
from realloc() means that the original pointer has not been freed.

[...]

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>

Jan 10 '07 #8

P: n/a
Crossposting a comp.lang.c thread to comp.std.c:

If realloc(nonnull, 0) returns NULL, has the object been freed?

Or, before this thread explodes: Is there already a definite answer
in a DR or some other thread?

Google found me plenty of threads about "does it return NULL?", and
some which touched the above question too, but I didn't find a clear
answer. Nor did I find a DR about it, but I don't know where to find
a list of all C99 DRs either.

Extracts from C99:

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 returned pointer shall not be used to access an object.

7.20.3.4 (The realloc function):
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 implementation may return NULL when size=0. The above implies
that if it does, realloc(nonnull, 0) frees the object first.

3 If memory for the new object cannot be allocated, the old object
is not deallocated and its value is unchanged.

4 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.

The implementation may try to return a non-NULL object. The above
implies that if it does, a NULL return comes from a realloc failure
and the object has not been freed.

C89 4.10.3.4 (or at least my draft of it) said realloc(nonnull, 0)
freed the object, but this sentence has been removed from C99.

--
Regards,
Hallvard
Jan 10 '07 #9

P: n/a
In article <hb**************@bombur.uio.no>,
Hallvard B Furuseth <h.**********@usit.uio.nowrote:
>The implementation may return NULL when size=0. The above implies
that if it does, realloc(nonnull, 0) frees the object first.
....
>The implementation may try to return a non-NULL object. The above
implies that if it does, a NULL return comes from a realloc failure
and the object has not been freed.
The question is surely whether, on a system that returns NULL for
malloc(0), a realloc(nonnull, 0) may *fail*, in which case it must
return NULL and not free the memory. This seems allowable but
perverse, since how can the system fail in such a case?

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Jan 11 '07 #10

P: n/a
Richard Tobin wrote:
In article <hb**************@bombur.uio.no>,
Hallvard B Furuseth <h.**********@usit.uio.nowrote:
>The implementation may return NULL when size=0. The above implies
that if it does, realloc(nonnull, 0) frees the object first.
...
>The implementation may try to return a non-NULL object. The above
implies that if it does, a NULL return comes from a realloc failure
and the object has not been freed.

The question is surely whether, on a system that returns NULL for
malloc(0), a realloc(nonnull, 0) may *fail*, in which case it must
return NULL and not free the memory. This seems allowable but
perverse, since how can the system fail in such a case?
The case for malloc(0) is unique and looks like realloc(NULL, 0). In my
view, malloc(0) should return NULL. It makes no sense to return a
pointer to zero bytes of storage. There is no case for
realloc(nonnull,0) to fail. free() does not have a failure mode.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Jan 11 '07 #11

P: n/a
ri*****@cogsci.ed.ac.uk (Richard Tobin) writes:
Hallvard B Furuseth <h.**********@usit.uio.nowrote:
>>The implementation may return NULL when size=0. The above implies
that if it does, realloc(nonnull, 0) frees the object first.
...
>>The implementation may try to return a non-NULL object. The above
implies that if it does, a NULL return comes from a realloc failure
and the object has not been freed.

The question is surely whether, on a system that returns NULL for
malloc(0), a realloc(nonnull, 0) may *fail*,
No. If realloc(nonnull, 0) attempts to return non-NULL, presumably
malloc(0) attemts the same - though I don't see that the standard
requires that.

--
Regards,
Hallvard
Jan 11 '07 #12

P: n/a
In article <hb*************@bombur.uio.no>,
Hallvard B Furuseth <h.**********@usit.uio.nowrote:
>The question is surely whether, on a system that returns NULL for
malloc(0), a realloc(nonnull, 0) may *fail*,
>No. If realloc(nonnull, 0) attempts to return non-NULL, presumably
malloc(0) attemts the same - though I don't see that the standard
requires that.
I was considering the case where both malloc() and realloc() return
NULL for zero bytes, but where - somehow - realloc(nonnull, 0) could
fail. In that case, realloc(nonnull, 0) would return NULL both
when it fails and succeeds, but when it fails the memory would not
have been freed.

Obviously it's absurd for realloc() to fail in that case, but I don't
know that the standard prohibits it.

-- Richard

--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Jan 11 '07 #13

P: n/a

Hallvard B Furuseth wrote:
Kenneth Brody writes:
The source to the runtime library I have here has this note:
(snip; although there are extra >s in the row before, there doesn't
seem to be an attribution line for them)
* (2) realloc(pblock, 0) is equivalent to free(pblock) (except that
* NULL is returned)

C89 4.10.3.4 says "If size is zero and ptr is not a null pointer, the
object it points to is freed." The clause has been deleted from C99.
In the context of C89/C90, what is the return value of
realloc(nonnull,0) and of realloc(0,0)? I've seen too many incorrect
compiler manuals to know truth from fiction about this, so I'd
appreciate C&V.
--
ais523

Jan 11 '07 #14

P: n/a
ri*****@cogsci.ed.ac.uk (Richard Tobin) writes:
Hallvard B Furuseth <h.**********@usit.uio.nowrote:
>>The question is surely whether, on a system that returns NULL for
malloc(0), a realloc(nonnull, 0) may *fail*,
>>No. If realloc(nonnull, 0) attempts to return non-NULL, presumably
malloc(0) attemts the same - though I don't see that the standard
requires that.

I was considering the case where both malloc() and realloc() return
NULL for zero bytes, but where - somehow - realloc(nonnull, 0) could
fail.
Yes, and that is _not_ what I was asking about. What I'm talking about
is: When realloc(nonnull, 0) has returned NULL, can the caller know
whether or not the object has been freed - when the caller doesn't know
whether or not the implementation always returns NULL from
realloc(nonnull, 0) (and malloc(0))?

--
Regards,
Hallvard
Jan 11 '07 #15

P: n/a
In article <hb**************@bombur.uio.no>,
Hallvard B Furuseth <h.**********@usit.uio.nowrote:
>Yes, and that is _not_ what I was asking about. What I'm talking about
is: When realloc(nonnull, 0) has returned NULL, can the caller know
whether or not the object has been freed - when the caller doesn't know
whether or not the implementation always returns NULL from
realloc(nonnull, 0) (and malloc(0))?
No. But again a good implementation would never fail for a realloc of
zero bytes: even if it would normally try to allocate a small block,
it can always succeed by returning the original nonnull value.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Jan 11 '07 #16

P: n/a

I think I can answer my own question now:
Does anyone know of a runtime where realloc() free'ed the object and
then returned NULL?
The following code:

char *p2;
char *p = malloc(100);
size_t nsize = 0;

if ((p2 = realloc(p, nsize)) == NULL) {
if (p) free(p);
p = NULL;
return NULL;
}
p = p2;

Compiled with Visual Studio Version 7, blows up on the call to free().

This is because realloc() returns NULL, suggesting that the realloc()
failed and the memory needs to be freed (but presumably already has).

As far as I can tell, this behavior is allowed by the standard.

I tried to write this up as the second example of MEM36-C at:

https://www.securecoding.cert.org/co...cating+0+bytes

I listed the following code as a compliant solution:

char *p2;
char *p = malloc(100);
....
if ( (nsize == 0) || (p2 = realloc(p, nsize)) == NULL) {
if (p) free(p);
p = NULL;
return NULL;
}
p = p2;

Please let me know if any of this is incorrect.

rCs
Jan 11 '07 #17

P: n/a
ais523 writes:
In the context of C89/C90, what is the return value of
realloc(nonnull,0)
NULL. The object is freed.
Last quoted sentence before Returns (only applies when arg!=NULL).
and of realloc(0,0)?
NULL or a new object.
First quoted sentence in 4.10.3.4, plus 4.10.3.
I've seen too many incorrect compiler manuals to know truth from
fiction about this, so I'd appreciate C&V.
ANSI C (equivalent to C89):

4.10.3 (Memory management functions):

If the size of the space requested is zero, the behavior is
implementation-defined; the value returned shall be either a null
pointer or a unique pointer.

4.10.3.4 (The realloc function):

If ptr is a null pointer, the realloc function behaves like the
malloc function for the specified size. (...) If the space cannot
be allocated, the object pointed to by ptr is unchanged. If size is
zero and ptr is not a null pointer, the object it points to is freed.

Returns
The realloc function returns either a null pointer or a pointer to
the possibly moved allocated space.

--
Hallvard
Jan 11 '07 #18

P: n/a
Hallvard B Furuseth wrote:
ais523 writes:
>In the context of C89/C90, what is the return value of
realloc(nonnull,0)

NULL. The object is freed.
Last quoted sentence before Returns (only applies when arg!=NULL).
>and of realloc(0,0)?

NULL or a new object.
First quoted sentence in 4.10.3.4, plus 4.10.3.
>I've seen too many incorrect compiler manuals to know truth from
fiction about this, so I'd appreciate C&V.

ANSI C (equivalent to C89):

4.10.3 (Memory management functions):

If the size of the space requested is zero, the behavior is
implementation-defined; the value returned shall be either a
null pointer or a unique pointer.

4.10.3.4 (The realloc function):

If ptr is a null pointer, the realloc function behaves like
the malloc function for the specified size. (...) If the
space cannot be allocated, the object pointed to by ptr is
unchanged. If size is zero and ptr is not a null pointer,
the object it points to is freed.

Returns
The realloc function returns either a null pointer or a
pointer to the possibly moved allocated space.
Which means that proper use of the realloc function, with:

if (tmp = realloc(p, size)) p = tmp;
else {
/* failure, take corrective action */
}

will fall into corrective action for a size of 0, and leave an
invalid value of p hanging about, which may well go BOOM on
eventual use (including free). Thus good implementations will not
return NULL for successful malloc/realloc/calloc of zero sizes.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Jan 12 '07 #19

P: n/a
"Hallvard B Furuseth" <h.**********@usit.uio.nowrote in message
news:hb**************@bombur.uio.no...
If realloc(nonnull, 0) returns NULL, has the object been freed?
No. realloc returns a null pointer (only) if the new object could
not be allocated, and if memory for the new object cannot be
allocated, the old objct is not deallocated and its value is unchanged.
Thats directly from the realloc spec (C99 7.20.3.4).
Jan 12 '07 #20

P: n/a
"Joe Wright" <jo********@comcast.netwrote...
The case for malloc(0) is unique and looks like realloc(NULL, 0). In my
view, malloc(0) should return NULL. It makes no sense to return a pointer
to zero bytes of storage. There is no case for realloc(nonnull,0) to fail.
free() does not have a failure mode.
Actually when size is specified as zero, there is explicit license
in the C standard for a conforming implementation to either
successfully allocate some amount of storage or to return a
null pointer (indicating allocation failure). The original
question cannot be resolved by taking that approach..
Jan 12 '07 #21

P: n/a
Douglas A. Gwyn writes:
>"Hallvard B Furuseth" <h.**********@usit.uio.nowrote in message
news:hb**************@bombur.uio.no...
>If realloc(nonnull, 0) returns NULL, has the object been freed?

No. realloc returns a null pointer (only) if the new object could
not be allocated, and if memory for the new object cannot be
allocated, the old objct is not deallocated and its value is unchanged.
Thats directly from the realloc spec (C99 7.20.3.4).
OK, I see it now. Though 7.20.3 says the allocation functions can
return NULL for size=0, the only text which says says realloc may free
the old object is for when it is going to return non-NULL. So this
case is opposite from C89, where realloc(nonnull, 0) freed the object.

Then a general realloc() call can be handled like this:

newobj = realloc(oldobj, size);
if (!newobj) {
#if __STDC_VERSION__ < 199901L
if (size)
#endif
free(oldobj);
return;
}

--
Hallvard
Jan 12 '07 #22

P: n/a
Hallvard B Furuseth wrote:
Douglas A. Gwyn writes:
"Hallvard B Furuseth" <h.**********@usit.uio.nowrote in message
news:hb**************@bombur.uio.no...
If realloc(nonnull, 0) returns NULL, has the object been freed?
No. realloc returns a null pointer (only) if the new object could
not be allocated, and if memory for the new object cannot be
allocated, the old objct is not deallocated and its value is unchanged.
Thats directly from the realloc spec (C99 7.20.3.4).

OK, I see it now. Though 7.20.3 says the allocation functions can
return NULL for size=0, the only text which says says realloc may free
the old object is for when it is going to return non-NULL. So this
case is opposite from C89, where realloc(nonnull, 0) freed the object.

Then a general realloc() call can be handled like this:

newobj = realloc(oldobj, size);
if (!newobj) {
#if __STDC_VERSION__ < 199901L
if (size)
#endif
free(oldobj);
return;
}
It seems to me that this causes massive problems for people wishing to
write libraries that conform both to C90 and to C99. Are there other
similar cases where the behaviour for a library call is defined in both
C90 and C99, but with different effects?

Jan 12 '07 #23

P: n/a
Harald van Dijk wrote:
>Hallvard B Furuseth wrote:
>Then a general realloc() call can be handled like this:

newobj = realloc(oldobj, size);
if (!newobj) {
#if __STDC_VERSION__ < 199901L
if (size)
#endif
free(oldobj);
return;
}

It seems to me that this causes massive problems for people wishing to
write libraries that conform both to C90 and to C99. (...)
Well, not all that massive in this case. I should have said "once you
have done realloc without checking the arguments, you can handle it like
this". It does get cumbersome if you want the assignment to be a
separate statement though.

--
Hallvard
Jan 12 '07 #24

P: n/a
[Reposting, previous post got out too soon]

Harald van Dijk wrote:
>Hallvard B Furuseth wrote:
>Then a general realloc() call can be handled like this:

newobj = realloc(oldobj, size);
if (!newobj) {
#if __STDC_VERSION__ < 199901L
if (size)
#endif
free(oldobj);
return;
}

It seems to me that this causes massive problems for people wishing to
write libraries that conform both to C90 and to C99. (...)
Well, not all that massive in this case. I should have said "once you
have done realloc without checking the arguments, you can handle it like
this". It does get cumbersome if you want the assignment to be a
separate statement though.

Otherwise:
if (!(size && (newobj = realloc(oldobj, size)))) {
free(oldobj);
return;
}

--
Hallvard
Jan 12 '07 #25

P: n/a
Hallvard B Furuseth wrote:
[Reposting, previous post got out too soon]
Harald van Dijk wrote:
Hallvard B Furuseth wrote:
Then a general realloc() call can be handled like this:

newobj = realloc(oldobj, size);
if (!newobj) {
#if __STDC_VERSION__ < 199901L
if (size)
#endif
free(oldobj);
return;
}
It seems to me that this causes massive problems for people wishing to
write libraries that conform both to C90 and to C99. (...)

Well, not all that massive in this case. [...]
Sorry that I wasn't clear; I copied too much of your post. I agree that
a program can easily be written that works with either C90 or C99's
realloc, but I was asking about a single realloc function that works
with either C90 or C99 programs.

Jan 12 '07 #26

P: n/a
Douglas A. Gwyn wrote:
"Joe Wright" <jo********@comcast.netwrote...
>The case for malloc(0) is unique and looks like realloc(NULL, 0). In my
view, malloc(0) should return NULL. It makes no sense to return a pointer
to zero bytes of storage. There is no case for realloc(nonnull,0) to fail.
free() does not have a failure mode.

Actually when size is specified as zero, there is explicit license
in the C standard for a conforming implementation to either
successfully allocate some amount of storage or to return a
null pointer (indicating allocation failure). The original
question cannot be resolved by taking that approach..
If the size argument is zero, allocation is not being attempted and I
see no rational case for a nonnull 'allocation success' return.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Jan 12 '07 #27

P: n/a
Douglas A. Gwyn wrote:
"Hallvard B Furuseth" <h.**********@usit.uio.nowrote in message
news:hb**************@bombur.uio.no...
>If realloc(nonnull, 0) returns NULL, has the object been freed?

No. realloc returns a null pointer (only) if the new object could
not be allocated, and if memory for the new object cannot be
allocated, the old objct is not deallocated and its value is unchanged.
Thats directly from the realloc spec (C99 7.20.3.4).

Surely realloc(nonnull, 0) cannot allocate zero bytes. This particular
call gets wrapped inside ..

void free(void *ptr) {
realloc(ptr, 0);
}

A NULL return from realloc here is just fine.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Jan 12 '07 #28

P: n/a
Hallvard B Furuseth wrote:
Then a general realloc() call can be handled like this:

newobj = realloc(oldobj, size);
if (!newobj) {
#if __STDC_VERSION__ < 199901L
if (size)
#endif
free(oldobj);
return;
}
If newobj is not a null pointer, then realloc was successful. If newobj
is a null pointer, and size != 0, then realloc failed. If newobj is a
null pointer and size == 0, then a priori there are two possibilities:
The allocation of 0 bytes was supposed to produce a non-null pointer
and failed (oldobj is intact), or it successfully returned a null
pointer (oldobj has been free()d).

In C99, it is implementation defined whether the size == 0 case behaves
as in C90 or tries to return a non-null pointer. To make the right
decision _after_ the realloc call, you have to use your knowledge of
the implementation.

You could write
if (size == 0) { free (oldobj); newobj = malloc (0); }
else { newobj = realloc (oldobj, size); if (newobj == NULL)
handle_failure (); }

Jan 12 '07 #29

P: n/a
Joe Wright wrote:
Douglas A. Gwyn wrote:
"Joe Wright" <jo********@comcast.netwrote...
The case for malloc(0) is unique and looks like realloc(NULL, 0). In my
view, malloc(0) should return NULL. It makes no sense to return a pointer
to zero bytes of storage. There is no case for realloc(nonnull,0) to fail.
free() does not have a failure mode.
Actually when size is specified as zero, there is explicit license
in the C standard for a conforming implementation to either
successfully allocate some amount of storage or to return a
null pointer (indicating allocation failure). The original
question cannot be resolved by taking that approach..
If the size argument is zero, allocation is not being attempted and I
see no rational case for a nonnull 'allocation success' return.
It's related to the 0-length data issue; although WG14
decided not to require support for 0-length arrays etc.,
it is undoubtedly more convenient for a programmer to have
p = malloc(n*sizeof(t));
rather than
p = n? malloc(n*sizeof(t)): NULL;
Presumably p would be used safely, since whatever loop
through array elements is coded would prevent dereferencing
p. p should have a different value than any other active
allocation, since that property is often used in programs.

Rather than require implementations to go one way or the
other on this, WG14 left it up to implementors to decide
what their users would prefer. Frankly, I think we should
have allowed 0-sized objects throughout the standard, for
reasons that we could discuss elsewhere.
Jan 13 '07 #30

P: n/a
Joe Wright wrote:
Surely realloc(nonnull, 0) cannot allocate zero bytes.
Sure it can; that is explicitly allowed by the C99 standard.
This particular call gets wrapped inside ..
void free(void *ptr) {
realloc(ptr, 0);
}
A NULL return from realloc here is just fine.
I must say I didn't understand that example. A conforming
implementation of the standard free function must *not* do
that, because either it fails to allocate and thus does not
free up the previous storage, or it successfully allocates,
frees the old storage, and the new block is lost track of,
causing a memory leak.
Jan 13 '07 #31

P: n/a
Joe Wright wrote:
Douglas A. Gwyn wrote:
>"Joe Wright" <jo********@comcast.netwrote...
>>The case for malloc(0) is unique and looks like realloc(NULL, 0).
In my view, malloc(0) should return NULL. It makes no sense to
return a pointer to zero bytes of storage. There is no case for
realloc(nonnull,0) to fail. free() does not have a failure mode.

Actually when size is specified as zero, there is explicit license
in the C standard for a conforming implementation to either
successfully allocate some amount of storage or to return a
null pointer (indicating allocation failure). The original
question cannot be resolved by taking that approach..

If the size argument is zero, allocation is not being attempted and I
see no rational case for a nonnull 'allocation success' return.
In all cases you alone are responsible for not using more memory
than you have allocated. If that value is 0, you obviously are not
allowed to use any of it. When the system returns a non-NULL value
for success, you can safely treat a return of NULL as an indication
of memory exhaustion (for at least the amount requested). It
simply keeps the treatment consistent, without special cases.

--
"I was born lazy. I am no lazier now than I was forty years
ago, but that is because I reached the limit forty years ago.
You can't go beyond possibility." -- Mark Twain
Jan 13 '07 #32

P: n/a
Joe Wright wrote:
Douglas A. Gwyn wrote:
>"Hallvard B Furuseth" <h.**********@usit.uio.nowrote in message
>>If realloc(nonnull, 0) returns NULL, has the object been freed?

No. realloc returns a null pointer (only) if the new object could
not be allocated, and if memory for the new object cannot be
allocated, the old objct is not deallocated and its value is
unchanged. Thats directly from the realloc spec (C99 7.20.3.4).
Surely realloc(nonnull, 0) cannot allocate zero bytes.
This particular call gets wrapped inside ..

void free(void *ptr) {
realloc(ptr, 0);
}

A NULL return from realloc here is just fine.
No, you still can't detect memory exhaustion. A system that has to
allocate a minimum space to keep track of things may not be able
to, due to complete exhaustion. It may be too stupid to just
reduce the size of the previously allocated block, and just does an
alloc, copy, free sequence internally. The problem doesn't arise
on free, it arises on the implied malloc. I would much rather
detect the problem as early as possible.

--
"I was born lazy. I am no lazier now than I was forty years
ago, but that is because I reached the limit forty years ago.
You can't go beyond possibility." -- Mark Twain

Jan 13 '07 #33

P: n/a
Douglas A. Gwyn wrote:
>realloc returns a null pointer (only) if the new object could
not be allocated, and if memory for the new object cannot be
allocated, the old objct is not deallocated and its value is unchanged.
Thats directly from the realloc spec (C99 7.20.3.4).
Joe Wright wrote:
Surely realloc(nonnull, 0) cannot allocate zero bytes.
Why not? If malloc() can allocate zero bytes, why can't realloc()?

I always assumed that a malloc(0) which returned a non-null
was meant to be used to "preallocate" objects whose sizes are
not known at the time of the malloc, but still needed to be
stored as non-null pointers somewhere. The fact that the
pointers are not null provides an indication that the objects
have been preallocated. Then, presumably, later calls to
realloc() are made to complete the allocations of the objects.

Likewise, I always assumed that realloc(p,0) was meant
to "mostly" deallocate an object but keep a non-null "place
holder" for it, so that it could later either be reallocated
with a definite nonzero size, or freed completely.

As a side issue, is an implementation allowed to return
the same value (besides NULL) for all malloc(0) calls?

-drt

Jan 13 '07 #34

P: n/a
"Douglas A. Gwyn" wrote:
Joe Wright wrote:
Douglas A. Gwyn wrote:
"Joe Wright" <jo********@comcast.netwrote...
>The case for malloc(0) is unique and looks like realloc(NULL, 0). In my
>view, malloc(0) should return NULL. It makes no sense to return a pointer
>to zero bytes of storage. There is no case for realloc(nonnull,0) to fail.
>free() does not have a failure mode.
Actually when size is specified as zero, there is explicit license
in the C standard for a conforming implementation to either
successfully allocate some amount of storage or to return a
null pointer (indicating allocation failure). The original
question cannot be resolved by taking that approach..
If the size argument is zero, allocation is not being attempted and I
see no rational case for a nonnull 'allocation success' return.

It's related to the 0-length data issue; although WG14
decided not to require support for 0-length arrays etc.,
it is undoubtedly more convenient for a programmer to have
p = malloc(n*sizeof(t));
rather than
p = n? malloc(n*sizeof(t)): NULL;
Presumably p would be used safely, since whatever loop
through array elements is coded would prevent dereferencing
p. p should have a different value than any other active
allocation, since that property is often used in programs.

Rather than require implementations to go one way or the
other on this, WG14 left it up to implementors to decide
what their users would prefer. Frankly, I think we should
have allowed 0-sized objects throughout the standard, for
reasons that we could discuss elsewhere.
Why do your quotes invariably seem to remove the inter-paragraph
blank lines? It makes them hard to read, and is very annoying.

--
"I was born lazy. I am no lazier now than I was forty years
ago, but that is because I reached the limit forty years ago.
You can't go beyond possibility." -- Mark Twain
Jan 13 '07 #35

P: n/a
"David R Tribble" <da***@tribble.comwrites:
As a side issue, is an implementation allowed to return
the same value (besides NULL) for all malloc(0) calls?
No:

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.
--
"Am I missing something?"
--Dan Pop
Jan 13 '07 #36

P: n/a
David R Tribble wrote:
I always assumed that a malloc(0) which returned a non-null
was meant to be used to "preallocate" objects whose sizes are
not known at the time of the malloc, but still needed to be
stored as non-null pointers somewhere. The fact that the
pointers are not null provides an indication that the objects
have been preallocated. Then, presumably, later calls to
realloc() are made to complete the allocations of the objects.
That would be one way to simplify certain algorithms.
Unfortunately, without a guarantee that malloc(0) has
to succeed (so long as storage remains available), a
portable program has to take more pains, perhaps
malloc(n?n:1)
As a side issue, is an implementation allowed to return
the same value (besides NULL) for all malloc(0) calls?
No; the spec says that at least one byte will be
actually allocated, and there is some general statement
that no two active heap allocations will overlap.
Jan 13 '07 #37

P: n/a
"Douglas A. Gwyn" wrote:
>
David R Tribble wrote:
I always assumed that a malloc(0) which returned a non-null
was meant to be used to "preallocate" objects whose sizes are
not known at the time of the malloc, but still needed to be
stored as non-null pointers somewhere. The fact that the
pointers are not null provides an indication that the objects
have been preallocated. Then, presumably, later calls to
realloc() are made to complete the allocations of the objects.

That would be one way to simplify certain algorithms.
Unfortunately, without a guarantee that malloc(0) has
to succeed (so long as storage remains available), a
portable program has to take more pains, perhaps
malloc(n?n:1)
As a side issue, is an implementation allowed to return
the same value (besides NULL) for all malloc(0) calls?

No; the spec says that at least one byte will be
actually allocated, and there is some general statement
that no two active heap allocations will overlap.
No.

7.20.3 p1 (n1124 or N869)

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.

Your "malloc(n ? n : 1)" will have problems if a macro whenever n
is an expression.

--
"The most amazing achievement of the computer software industry
is its continuing cancellation of the steady and staggering
gains made by the computer hardware industry..." - Petroski
Jan 13 '07 #38

P: n/a
"CBFalconer" <cb********@yahoo.comwrote in message
news:45***************@yahoo.com...
"Douglas A. Gwyn" wrote:
>David R Tribble wrote:
I always assumed that a malloc(0) which returned a non-null
was meant to be used to "preallocate" objects whose sizes are
not known at the time of the malloc, but still needed to be
stored as non-null pointers somewhere. The fact that the
pointers are not null provides an indication that the objects
have been preallocated. Then, presumably, later calls to
realloc() are made to complete the allocations of the objects.
That would be one way to simplify certain algorithms.
Unfortunately, without a guarantee that malloc(0) has
to succeed (so long as storage remains available), a
portable program has to take more pains, perhaps
malloc(n?n:1)
As a side issue, is an implementation allowed to return
the same value (besides NULL) for all malloc(0) calls?
No; the spec says that at least one byte will be
actually allocated, and there is some general statement
that no two active heap allocations will overlap.
No.
7.20.3 p1 (n1124 or N869)
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.
Did you even read the previous message before responding?
Your "malloc(n ? n : 1)" will have problems if a macro whenever n
is an expression.
Obviously it was not a macro definition.
Jan 13 '07 #39

P: n/a
"Douglas A. Gwyn" wrote:
"CBFalconer" <cb********@yahoo.comwrote in message
>"Douglas A. Gwyn" wrote:
.... snip ...
>>>
No; the spec says that at least one byte will be
actually allocated, and there is some general statement
that no two active heap allocations will overlap.
>No.
7.20.3 p1 (n1124 or N869)
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.

Did you even read the previous message before responding?
Yes. You stated that at least one byte would be allocated. I
disputed that.

--
Some informative links:
<http://members.fortunecity.com/nnqweb/ (newusers)
<http://www.catb.org/~esr/faqs/smart-questions.html>
<http://www.caliburn.nl/topposting.html>
<http://www.netmeister.org/news/learn2quote.html>
<http://cfaj.freeshell.org/google/ (taming google)

Jan 14 '07 #40

P: n/a
CBFalconer wrote:
"Douglas A. Gwyn" wrote:
"CBFalconer" <cb********@yahoo.comwrote in message
"Douglas A. Gwyn" wrote:
... snip ...
[un-snip start]
>David R Tribble wrote:
As a side issue, is an implementation allowed to return
the same value (besides NULL) for all malloc(0) calls?
[un-snip end]
>>
No; the spec says that at least one byte will be
actually allocated, and there is some general statement
that no two active heap allocations will overlap.
No.
7.20.3 p1 (n1124 or N869)
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.
Did you even read the previous message before responding?

Yes. You stated that at least one byte would be allocated. I
disputed that.
He stated that at least one byte would be allocated if the result is
not NULL, which is correct.

Jan 14 '07 #41

P: n/a
Harald van D?k wrote:
CBFalconer wrote:
>"Douglas A. Gwyn" wrote:
.... snip ...
>>>
Did you even read the previous message before responding?

Yes. You stated that at least one byte would be allocated. I
disputed that.

He stated that at least one byte would be allocated if the
result is not NULL, which is correct.
Pedantically, no. However we are arguing over the density of
angels on pinheads, which is not productive.

--
"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies." -- C. A. R. Hoare

Jan 14 '07 #42

P: n/a
"CBFalconer" <cb********@yahoo.comwrote in message
news:45***************@yahoo.com...
Harald van D?k wrote:
>CBFalconer wrote:
>>"Douglas A. Gwyn" wrote:
... snip ...
>>>Did you even read the previous message before responding?
Yes. You stated that at least one byte would be allocated. I
disputed that.
He stated that at least one byte would be allocated if the
result is not NULL, which is correct.
Pedantically, no. However we are arguing over the density of
angels on pinheads, which is not productive.
Actually, yes -- it was so stipulated in the portion that you
snipped out.
Jan 14 '07 #43

P: n/a

Hallvard B Furuseth wrote:
[Reposting, previous post got out too soon]

Harald van Dk wrote:
Hallvard B Furuseth wrote:
Then a general realloc() call can be handled like this:

newobj = realloc(oldobj, size);
if (!newobj) {
#if __STDC_VERSION__ < 199901L
if (size)
#endif
free(oldobj);
return;
}
It seems to me that this causes massive problems for people wishing to
write libraries that conform both to C90 and to C99. (...)

Well, not all that massive in this case. I should have said "once you
have done realloc without checking the arguments, you can handle it like
this". It does get cumbersome if you want the assignment to be a
separate statement though.

Otherwise:
if (!(size && (newobj = realloc(oldobj, size)))) {
free(oldobj);
return;
}
Those two examples given above do not have the same behavior, which
probably was intended; on an implementation where malloc(0) returns
a non-null pointer the former passes through without returning while
the latter returns after an explicit call to free. Furthermore,
strictly speaking, the former is not strictly conforming to C90.
--
Jun, Woong (woong at icu.ac.kr)
Samsung Electronics Co., Ltd.

``All opinions expressed are mine, and do not represent
the official opinions of any organization.''

Jan 15 '07 #44

P: n/a
Jun Woong writes:
>Hallvard B Furuseth wrote:
>>Harald van Dk wrote:
>>>Hallvard B Furuseth wrote:
Then a general realloc() call can be handled like this:

newobj = realloc(oldobj, size);
if (!newobj) {
#if __STDC_VERSION__ < 199901L
if (size)
#endif
free(oldobj);
return;
}

It seems to me that this causes massive problems for people wishing to
write libraries that conform both to C90 and to C99. (...)

Well, not all that massive in this case. I should have said "once you
have done realloc without checking the arguments, you can handle it like
this". It does get cumbersome if you want the assignment to be a
separate statement though.

Otherwise:
if (!(size && (newobj = realloc(oldobj, size)))) {
free(oldobj);
return;
}

Those two examples given above do not have the same behavior, which
probably was intended; (...)
No, I didn't really think of that. Just the simplest way to deal with
realloc(,0) after and before the call.
Furthermore, strictly speaking, the former is not strictly conforming
to C90.
Shrug. If we are going to be that paranoid about constants like
__STDC_VERSION__ or __cplusplus, it'd be no use to introduce them at all.

--
Hallvard
Jan 18 '07 #45

P: n/a

Hallvard B Furuseth wrote:
Jun Woong writes:
[...]

Those two examples given above do not have the same behavior, which
probably was intended; (...)

No, I didn't really think of that. Just the simplest way to deal with
realloc(,0) after and before the call.
Yes, the difference really originates from a point of time when a
call to realloc with the size 0 is handled.
Furthermore, strictly speaking, the former is not strictly conforming
to C90.

Shrug. If we are going to be that paranoid about constants like
__STDC_VERSION__ or __cplusplus, it'd be no use to introduce them at all.
It would never cause a problem in practice. But this is comp.std.c;
I meant pedanticism with "strictly speaking."
--
Jun, Woong (woong at icu.ac.kr)
Samsung Electronics Co., Ltd.

``All opinions expressed are mine, and do not represent
the official opinions of any organization.''

Jan 18 '07 #46

P: n/a
"Jun Woong" <wo***@icu.ac.krwrites:
[...]
It would never cause a problem in practice. But this is comp.std.c;
I meant pedanticism with "strictly speaking."
Surely you mean "pedantry" rather than "pedanticism".

8-)}

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 18 '07 #47

P: n/a

Keith Thompson wrote:
"Jun Woong" <wo***@icu.ac.krwrites:
[...]
It would never cause a problem in practice. But this is comp.std.c;
I meant pedanticism with "strictly speaking."

Surely you mean "pedantry" rather than "pedanticism".
<OT>

My Korean-English dictionary says that they refer to the same
meaning. Is there any (subtle?) difference I didn't recognize?

</OT>
--
Jun, Woong (woong at icu.ac.kr)
Samsung Electronics Co., Ltd.

``All opinions expressed are mine, and do not represent
the official opinions of any organization.''

Jan 18 '07 #48

P: n/a
"Jun Woong" <wo***@icu.ac.krwrites:
Keith Thompson wrote:
"Jun Woong" <wo***@icu.ac.krwrites:
[...]
It would never cause a problem in practice. But this is comp.std.c;
I meant pedanticism with "strictly speaking."
Surely you mean "pedantry" rather than "pedanticism".

<OT>

My Korean-English dictionary says that they refer to the same
meaning. Is there any (subtle?) difference I didn't recognize?
I think they probably mean the same thing. I was more interested in
making a joke than in strict accuracy.
</OT>
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 19 '07 #49

P: n/a
Keith Thompson wrote:
"Jun Woong" <wo***@icu.ac.krwrites:
>Keith Thompson wrote:
>>"Jun Woong" <wo***@icu.ac.krwrites:
[...]
It would never cause a problem in practice. But this is comp.std.c;
I meant pedanticism with "strictly speaking."

Surely you mean "pedantry" rather than "pedanticism".

My Korean-English dictionary says that they refer to the same
meaning. Is there any (subtle?) difference I didn't recognize?

I think they probably mean the same thing. I was more interested
in making a joke than in strict accuracy.
I think they are subtly different, but I can't quite put my finger
on it. To me, pedantry implies use, while pedanticism implies
adherence to the practice.

"He indulged in pedantry in his reply"
vs
"He is a confirmed pedanticist" or "He practices pedanticism"

Added cross-post to alt.usage.english

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Jan 19 '07 #50

64 Replies

This discussion thread is closed

Replies have been disabled for this discussion.