Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: realloc zero bytes?

100 views
Skip to first unread message

Hallvard B Furuseth

unread,
Jan 10, 2007, 5:42:35 PM1/10/07
to
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

Richard Tobin

unread,
Jan 10, 2007, 7:31:32 PM1/10/07
to
In article <hbf.2007...@bombur.uio.no>,

Hallvard B Furuseth <h.b.fu...@usit.uio.no> wrote:

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

Joe Wright

unread,
Jan 10, 2007, 8:28:12 PM1/10/07
to
Richard Tobin wrote:
> In article <hbf.2007...@bombur.uio.no>,
> Hallvard B Furuseth <h.b.fu...@usit.uio.no> wrote:
>
>> 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 ---

Hallvard B Furuseth

unread,
Jan 11, 2007, 4:43:52 AM1/11/07
to
ric...@cogsci.ed.ac.uk (Richard Tobin) writes:
> Hallvard B Furuseth <h.b.fu...@usit.uio.no> wrote:
>>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

Richard Tobin

unread,
Jan 11, 2007, 7:15:09 AM1/11/07
to
In article <hbf.200...@bombur.uio.no>,

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.

Hallvard B Furuseth

unread,
Jan 11, 2007, 7:30:06 AM1/11/07
to
ric...@cogsci.ed.ac.uk (Richard Tobin) writes:
> Hallvard B Furuseth <h.b.fu...@usit.uio.no> wrote:
>>> 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

Richard Tobin

unread,
Jan 11, 2007, 7:40:49 AM1/11/07
to
In article <hbf.2007...@bombur.uio.no>,

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.

Douglas A. Gwyn

unread,
Jan 12, 2007, 1:11:23 AM1/12/07
to
"Hallvard B Furuseth" <h.b.fu...@usit.uio.no> wrote in message
news:hbf.2007...@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).


Douglas A. Gwyn

unread,
Jan 12, 2007, 1:14:24 AM1/12/07
to
"Joe Wright" <joeww...@comcast.net> wrote...

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


Hallvard B Furuseth

unread,
Jan 12, 2007, 6:47:02 AM1/12/07
to

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

Harald van Dijk

unread,
Jan 12, 2007, 7:16:09 AM1/12/07
to

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?

Hallvard B Furuseth

unread,
Jan 12, 2007, 7:27:01 AM1/12/07
to
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

Hallvard B Furuseth

unread,
Jan 12, 2007, 7:29:41 AM1/12/07
to
[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

Harald van Dijk

unread,
Jan 12, 2007, 7:42:30 AM1/12/07
to
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.

Joe Wright

unread,
Jan 12, 2007, 5:32:50 PM1/12/07
to
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

unread,
Jan 12, 2007, 5:55:41 PM1/12/07
to
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.

christian.bau

unread,
Jan 12, 2007, 6:03:39 PM1/12/07
to
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 (); }

Douglas A. Gwyn

unread,
Jan 12, 2007, 7:59:34 PM1/12/07
to
Joe Wright wrote:
> Douglas A. Gwyn wrote:
> > "Joe Wright" <joeww...@comcast.net> wrote...
> >> 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.

Douglas A. Gwyn

unread,
Jan 12, 2007, 8:05:43 PM1/12/07
to
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.

CBFalconer

unread,
Jan 12, 2007, 8:11:42 PM1/12/07
to
Joe Wright wrote:
> Douglas A. Gwyn wrote:
>> "Hallvard B Furuseth" <h.b.fu...@usit.uio.no> wrote 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

CBFalconer

unread,
Jan 12, 2007, 8:04:53 PM1/12/07
to
Joe Wright wrote:
> Douglas A. Gwyn wrote:
>> "Joe Wright" <joeww...@comcast.net> wrote...
>>
>>> 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.

David R Tribble

unread,
Jan 12, 2007, 10:52:50 PM1/12/07
to
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

CBFalconer

unread,
Jan 12, 2007, 10:09:02 PM1/12/07
to

Why do your quotes invariably seem to remove the inter-paragraph
blank lines? It makes them hard to read, and is very annoying.

Ben Pfaff

unread,
Jan 12, 2007, 11:37:12 PM1/12/07
to
"David R Tribble" <da...@tribble.com> writes:

> 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

Douglas A. Gwyn

unread,
Jan 13, 2007, 12:57:51 AM1/13/07
to
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.

CBFalconer

unread,
Jan 13, 2007, 8:20:17 AM1/13/07
to

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


Douglas A. Gwyn

unread,
Jan 13, 2007, 6:11:35 PM1/13/07
to
"CBFalconer" <cbfal...@yahoo.com> wrote in message
news:45A8DC91...@yahoo.com...

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.


CBFalconer

unread,
Jan 13, 2007, 7:19:48 PM1/13/07
to
"Douglas A. Gwyn" wrote:
> "CBFalconer" <cbfal...@yahoo.com> wrote 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)

Harald van Dijk

unread,
Jan 13, 2007, 8:02:48 PM1/13/07
to
CBFalconer wrote:
> "Douglas A. Gwyn" wrote:
> > "CBFalconer" <cbfal...@yahoo.com> wrote 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.

CBFalconer

unread,
Jan 13, 2007, 8:33:05 PM1/13/07
to
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

Douglas A. Gwyn

unread,
Jan 14, 2007, 7:09:53 AM1/14/07
to
"CBFalconer" <cbfal...@yahoo.com> wrote in message
news:45A98851...@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.


Jun Woong

unread,
Jan 15, 2007, 2:59:18 AM1/15/07
to

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

Hallvard B Furuseth

unread,
Jan 18, 2007, 7:49:39 AM1/18/07
to
Jun Woong writes:

>Hallvard B Furuseth wrote:
>>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;
>> }
>>
>
> 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

Jun Woong

unread,
Jan 18, 2007, 8:40:38 AM1/18/07
to

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

Keith Thompson

unread,
Jan 18, 2007, 3:06:38 PM1/18/07
to
"Jun Woong" <wo...@icu.ac.kr> writes:
[...]

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

Jun Woong

unread,
Jan 18, 2007, 6:28:55 PM1/18/07
to

Keith Thompson wrote:

> "Jun Woong" <wo...@icu.ac.kr> writes:
> [...]
> > 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>

Keith Thompson

unread,
Jan 18, 2007, 8:14:39 PM1/18/07
to
"Jun Woong" <wo...@icu.ac.kr> writes:
> Keith Thompson wrote:
>
> > "Jun Woong" <wo...@icu.ac.kr> writes:
> > [...]
> > > 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>

CBFalconer

unread,
Jan 18, 2007, 10:49:27 PM1/18/07
to
Keith Thompson wrote:
> "Jun Woong" <wo...@icu.ac.kr> writes:
>> Keith Thompson wrote:
>>> "Jun Woong" <wo...@icu.ac.kr> writes:
>>> [...]
>>>> 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>


Jun Woong

unread,
Jan 19, 2007, 12:33:06 AM1/19/07
to

CBFalconer wrote:

> Keith Thompson wrote:
> > "Jun Woong" <wo...@icu.ac.kr> writes:
> >> Keith Thompson wrote:
> >>> "Jun Woong" <wo...@icu.ac.kr> writes:
> >>> [...]
> >>>> 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"
>

Oh, then, as Keith pointed out, "pedanticism" in my post should read
as "pedantry." ;-)

Richard Heathfield

unread,
Jan 19, 2007, 1:40:38 AM1/19/07
to
Keith Thompson said:

> "Jun Woong" <wo...@icu.ac.kr> writes:
> [...]
>> 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".

Your spelling is fine, but your pronunciation is incorrect.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.

David R Tribble

unread,
Jan 19, 2007, 11:18:49 AM1/19/07
to
David R Tribble wrote:
>> As a side issue, is an implementation allowed to return
>> the same value (besides NULL) for all malloc(0) calls?
>

Douglas A. Gwyn wrote:
> 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.

I didn't think so.

Another side issue. 7.20.3 says:
The pointer returned if the allocation succeeds is suitably aligned
so that it may be assigned to a pointer to any type of object [A]
and then used to access such an object or an array of such objects
in the space allocated

I assume we could insert at [A] the phrase:
having a size not greater than the allocated space

In other words, if I malloc two bytes, I can't expect that I can store
"any type of object" in the space (such as a 4-byte float). Nor should
I expect that the space allocated is "suitably aligned" for any object
type larger than two bytes, right?

-drt

Wojtek Lerch

unread,
Jan 19, 2007, 12:03:03 PM1/19/07
to
"David R Tribble" <da...@tribble.com> wrote in message
news:1169223529.2...@11g2000cwr.googlegroups.com...

> In other words, if I malloc two bytes, I can't expect that I can store
> "any type of object" in the space (such as a 4-byte float). Nor should
> I expect that the space allocated is "suitably aligned" for any object
> type larger than two bytes, right?

No, I think the standard does promise that this is defined:

float *foo = malloc( 1 );

Clark S. Cox III

unread,
Jan 19, 2007, 2:16:32 PM1/19/07
to
David R Tribble wrote:
> David R Tribble wrote:
>>> As a side issue, is an implementation allowed to return
>>> the same value (besides NULL) for all malloc(0) calls?
>
> Douglas A. Gwyn wrote:
>> 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.
>
> I didn't think so.
>
> Another side issue. 7.20.3 says:
> The pointer returned if the allocation succeeds is suitably aligned
> so that it may be assigned to a pointer to any type of object [A]
> and then used to access such an object or an array of such objects
> in the space allocated
>
> I assume we could insert at [A] the phrase:
> having a size not greater than the allocated space

Why make such an assumption; it is counter to what the standard already
says.

> In other words, if I malloc two bytes, I can't expect that I can store
> "any type of object" in the space (such as a 4-byte float). Nor should
> I expect that the space allocated is "suitably aligned" for any object
> type larger than two bytes, right?

AIUI, the alignment is absolute. If malloc returns a non-NULL pointer,
it is aligned suitably for *any* type, period. I see nothing undefined
about:

double *d = malloc(1);

Of course, if sizeof(double) is greater than 1, then dereferencing or
incrementing d would be undefined.

--
Clark S. Cox III
clar...@gmail.com

Richard Tobin

unread,
Jan 19, 2007, 4:19:07 PM1/19/07
to
In article <12r2682...@corp.supernews.com>,

Clark S. Cox III <clar...@gmail.com> wrote:

>AIUI, the alignment is absolute. If malloc returns a non-NULL pointer,
>it is aligned suitably for *any* type, period. I see nothing undefined
>about:
>
> double *d = malloc(1);
>
>Of course, if sizeof(double) is greater than 1, then dereferencing or
>incrementing d would be undefined.

But if sizeof(double) is greater than one, how can you observe whether
or not the address is adequately aligned for a double? All conforming
programs work even if the alignment is wrong.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.

Douglas A. Gwyn

unread,
Jan 19, 2007, 3:59:42 PM1/19/07
to
David R Tribble wrote:
> Another side issue. 7.20.3 says:
> The pointer returned if the allocation succeeds is suitably aligned
> so that it may be assigned to a pointer to any type of object [A]
> and then used to access such an object or an array of such objects
> in the space allocated
> I assume we could insert at [A] the phrase:
> having a size not greater than the allocated space

That's a different requirement. The intent is to have the same
more-stringent alignment requirement even for pointers to tiny
allocations (which would be a natural property of most malloc
implementations anyway).

Of course the "any type ... and then used to access" is meant
to be subject to the requirement that the accessed object
representation lie entirely within the array of bytes
allocated (which cannot be assumed to be more than the size
requested). That probably falls out of generic requirements
elsewhere in the standard.

Ben Pfaff

unread,
Jan 19, 2007, 4:25:12 PM1/19/07
to
ric...@cogsci.ed.ac.uk (Richard Tobin) writes:

> In article <12r2682...@corp.supernews.com>,
> Clark S. Cox III <clar...@gmail.com> wrote:
>
>>AIUI, the alignment is absolute. If malloc returns a non-NULL pointer,
>>it is aligned suitably for *any* type, period. I see nothing undefined
>>about:
>>
>> double *d = malloc(1);
>>
>>Of course, if sizeof(double) is greater than 1, then dereferencing or
>>incrementing d would be undefined.
>
> But if sizeof(double) is greater than one, how can you observe whether
> or not the address is adequately aligned for a double? All conforming
> programs work even if the alignment is wrong.

Converting to a pointer type for which the pointer value is
misaligned yields undefined behavior in itself. See C99 6.3.2.3:

A pointer to an object or incomplete type may be converted
to a pointer to a different object or incomplete type. If
the resulting pointer is not correctly aligned57) for the
pointed-to type, the behavior is undefined.

Thus, "double *d = malloc(1);" is well-defined, but "char c;
double d = &c;" is not.
--
Ben Pfaff
b...@cs.stanford.edu
http://benpfaff.org

Richard Tobin

unread,
Jan 19, 2007, 4:45:29 PM1/19/07
to
In article <87y7nys...@blp.benpfaff.org>,
Ben Pfaff <b...@cs.stanford.edu> wrote:

>>>Of course, if sizeof(double) is greater than 1, then dereferencing or
>>>incrementing d would be undefined.

>> But if sizeof(double) is greater than one, how can you observe whether
>> or not the address is adequately aligned for a double? All conforming
>> programs work even if the alignment is wrong.

>Converting to a pointer type for which the pointer value is
>misaligned yields undefined behavior in itself.

On a system where that in fact generates an error, malloc(1) could not
returned an insufficiently aligned address. But on a system where
that is not the case, malloc(1) *is* sufficiently aligned for all the
things you can legally do with it. That is, these systems behave *as
if* malloc(1) was sufficiently aligned for a double.

Ben Pfaff

unread,
Jan 19, 2007, 4:49:00 PM1/19/07
to
ric...@cogsci.ed.ac.uk (Richard Tobin) writes:

> In article <87y7nys...@blp.benpfaff.org>,
> Ben Pfaff <b...@cs.stanford.edu> wrote:
>
>>>>Of course, if sizeof(double) is greater than 1, then dereferencing or
>>>>incrementing d would be undefined.
>
>>> But if sizeof(double) is greater than one, how can you observe whether
>>> or not the address is adequately aligned for a double? All conforming
>>> programs work even if the alignment is wrong.
>
>>Converting to a pointer type for which the pointer value is
>>misaligned yields undefined behavior in itself.
>
> On a system where that in fact generates an error, malloc(1) could not
> returned an insufficiently aligned address. But on a system where
> that is not the case, malloc(1) *is* sufficiently aligned for all the
> things you can legally do with it. That is, these systems behave *as
> if* malloc(1) was sufficiently aligned for a double.

I don't think that contradicts anything I said, although it does
clarify it.
--
Here's a tip: null pointers don't have to be *dull* pointers!

Keith Thompson

unread,
Jan 19, 2007, 8:50:35 PM1/19/07
to
ric...@cogsci.ed.ac.uk (Richard Tobin) writes:
> In article <87y7nys...@blp.benpfaff.org>,
> Ben Pfaff <b...@cs.stanford.edu> wrote:
>
> >>>Of course, if sizeof(double) is greater than 1, then dereferencing or
> >>>incrementing d would be undefined.
>
> >> But if sizeof(double) is greater than one, how can you observe whether
> >> or not the address is adequately aligned for a double? All conforming
> >> programs work even if the alignment is wrong.
>
> >Converting to a pointer type for which the pointer value is
> >misaligned yields undefined behavior in itself.
>
> On a system where that in fact generates an error, malloc(1) could not
> returned an insufficiently aligned address. But on a system where
> that is not the case, malloc(1) *is* sufficiently aligned for all the
> things you can legally do with it. That is, these systems behave *as
> if* malloc(1) was sufficiently aligned for a double.

I think I agree.

Suppose sizeof(double)==8, and double requires 8-byte alignment. But
suppose that converting a misaligned char* pointer to double* (which
invokes undefined behavior) simply copies the bit pattern, and never
causes anything "bad" to happen. In other words, attempting to access
a misaligned double object can crash your program, but constructing a
misaligned pointer to double cannot. (These are assumptions about a
particular hypothetical implementation.)

Then the standard's definition of malloc() explicitly requires
double *ptr = malloc(1);
(assuming it succeeds) to set ptr to a value that's properly aligned
(i.e., 8-byte aligned) for type double -- but there's no way for a
portable program to detect a violation of this requirement. So I
think the "as if" rule applies.

If a tree is misaligned in a forest and nobody can access it, does it
invoke undefined behavior?

Note that if the result of malloc(1) is misaligned, then
realloc(ptr, sizeof(double))
will not be able to expand the allocated space in place; it must
allocate a *new* properly aligned 8-byte block. This doesn't argue
that malloc(1) can't yield a misaligned pointer, merely that the
implementation must take some extra care if it does so.

Douglas A. Gwyn

unread,
Jan 20, 2007, 1:20:15 AM1/20/07
to
"Keith Thompson" <ks...@mib.org> wrote in message
news:lnr6tqv...@nuthaus.mib.org...

> Suppose sizeof(double)==8, and double requires 8-byte alignment. But
> suppose that converting a misaligned char* pointer to double* (which
> invokes undefined behavior) simply copies the bit pattern, and never
> causes anything "bad" to happen. In other words, attempting to access
> a misaligned double object can crash your program, but constructing a
> misaligned pointer to double cannot. (These are assumptions about a
> particular hypothetical implementation.)

Well, if you assume nothing can go wrong then of course you can
conclude that nothing can go wrong. However, a not-strictly-
conforming program could inspect the returned address in an
implementation-dependent way and still determine that it has
improper alignment, taking a branch that a conforming
implementation must not allow to happen.

The requirements on a conforming implementation are not limited
to compilation of s.c. programs.


Keith Thompson

unread,
Jan 20, 2007, 4:01:42 AM1/20/07
to

Um, where did I mention strictly conforming programs?

Any code that examines a pointer value and determines whether it's
properly aligned must depend on (at least) implementation-defined
behavior. For example, it might convert the pointer value to an
integer type and examine the low-order bits, or convert it to a string
using sprintf("%p", ptr); both conversions are implementation-defined.

But I don't see anything that requires an implementation to define
these conversions in a way that allows a program to determine the
pointer value's alignment. I can imagine an implementation in which
malloc(1) returns a misaligned pointer, but no program, using the
standard and the implementation's required documentation, can prove
this.

Before we get too far into this, let me say that *this* particular
issue is, in my opinion, no big deal. I think there's a requirement
in the standard that can, for some implementations, be violated more
or less undetectably. It's an interesting theoretical tidbit, but I
don't think there are any significant consequences.

Mike Lyle

unread,
Jan 19, 2007, 12:57:02 PM1/19/07
to
Jun Woong wrote:
> CBFalconer wrote:
>
>> Keith Thompson wrote:
>>> "Jun Woong" <wo...@icu.ac.kr> writes:
>>>> Keith Thompson wrote:
>>>>> "Jun Woong" <wo...@icu.ac.kr> writes:
>>>>> [...]
>>>>>> 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"
>>
>
> Oh, then, as Keith pointed out, "pedanticism" in my post should read
> as "pedantry." ;-)

I find that OED doesn't make CBF's distinction, and its most recent
example of "pedanticism" came from Roy Jenkins. Even if that in itself
isn't enough to recommend using "pedantry" instead, I think the word is
a syllable too far. I suppose we could support the term for something
like "holding to pedantry as a way of life", but I'd want to see some
credible examples.

--
Mike.

--
Posted via a free Usenet account from http://www.teranews.com

Flash Gordon

unread,
Jan 22, 2007, 2:32:52 PM1/22/07
to
Mike Lyle wrote, On 19/01/07 17:57:

<snip>

> I find that OED doesn't make CBF's distinction, and its most recent
> example of "pedanticism" came from Roy Jenkins. Even if that in itself
> isn't enough to recommend using "pedantry" instead, I think the word is
> a syllable too far. I suppose we could support the term for something
> like "holding to pedantry as a way of life", but I'd want to see some
> credible examples.

How about "the regulars of comp.lang.c believe in pedanticism"? ;-)
--
Flash Gordon

SuperKoko

unread,
Jan 31, 2007, 7:15:42 AM1/31/07
to
On Jan 20, 7:20 am, "Douglas A. Gwyn" <DAG...@null.net> wrote:
> "Keith Thompson" <k...@mib.org> wrote in message
<off-topic>
Yes, I agree. It brings an interesting point (a bit off topic on
comp.std.c, sorry).
Any implementation on a specific platform (for example IA-32 under
Win32), is not required to document the internals of pointers. And I'm
pretty sure that most of them don't document it.
That way, programmers mustn't assume (but far too many do assume) that
the compiler uses a particular representation, and assuming that, they
invoke non-documented undefined behavior (breaking basic assumptions
of a compiler), and, they discover that things may not work as
expected. For example, they may discover "mis-aligned" pointers
returned by malloc.
The "as-if" rule makes that, an implementation may induce concepts
that aren't visible in the underlying hardware, such as trap
representations or weird pointer representations.

In short words (you probably all know that on comp.std.c): Hardware
doesn't dictate at all what is in a C implementation. The
documentation does it.
</off-topic>

However, I would like to point out that this piece of code is (maybe)
portable. I'm not sure since it's "border-line".

char* p0=malloc(1),*p1=malloc(sizeof(double)-1);
if (p0 && p1 && p0+1==p1) {
*((double*)p0)=42.3; /* here, I'm not sure that this statement is
valid... If it's invalid, I would like to know why */
}
free(p0);free(p1);

p0+1 is a valid expression (pointer to one past the last element of an
array).
p0+1 == p1 is a valid expression. You can compare any two pointers...
result of this comparison is unspecified.

Of course, it's very likely not to return true!

So, if an implementation makes this p0+1==p1 expression always return
0 (for example, allocating one extra byte when malloc'ing, or using
bound checks, or any other reliable mean), malloc can return a pointer
mis-aligned at hardware level (except if the documentation of this
compiler provides a mean to detect this mis-alignment).
In that case, the "as-if" rule is respected.

Jun Woong

unread,
Jan 31, 2007, 7:32:10 PM1/31/07
to
"SuperKoko" <MetaEntr...@gmail.com> wrote:
[...]

>
> However, I would like to point out that this piece of code is (maybe)
> portable. I'm not sure since it's "border-line".
>
> char* p0=malloc(1),*p1=malloc(sizeof(double)-1);
> if (p0 && p1 && p0+1==p1) {
> *((double*)p0)=42.3; /* here, I'm not sure that this statement is
> valid... If it's invalid, I would like to know why */}
>

If you mean strict conformance to the standard by "valid," I can't
believe you said that. p0 and p1 point to two distinct objects which
happen to be adjacent in the sense of the pointer arithmetic that
constitutes the logical address space for C programs. I see nothing
from the standard to make it differ from

T *p = malloc(sizeof(*p)-1);
*p = valid_value_for_type_T;

Of course, the standard needs be revised to surely say
"non-conformance" to this kind of code. Though your code would be
fairly portable in practice.

> free(p0);free(p1);
>
> p0+1 is a valid expression (pointer to one past the last element of an
> array).
> p0+1 == p1 is a valid expression. You can compare any two pointers...
> result of this comparison is unspecified.
>
> Of course, it's very likely not to return true!
>
> So, if an implementation makes this p0+1==p1 expression always return
> 0 (for example, allocating one extra byte when malloc'ing, or using
> bound checks, or any other reliable mean), malloc can return a pointer
> mis-aligned at hardware level (except if the documentation of this
> compiler provides a mean to detect this mis-alignment).

If there is NO mean to detect a misaligned pointer on an
implementation, I think it means simply there is nothing called
"misaligned pointers" on it.

0 new messages