Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > ??alloc(0) - std interpretation

Reply
Thread Tools

??alloc(0) - std interpretation

 
 
sNOiSPAMt@amu.edu.pl
Guest
Posts: n/a
 
      05-17-2004

7.20.3#1
[...] If the size of the space requested is
zero, the behavior is implementation-defined: either a null
pointer is returned, or the behavior is as if the size were
some nonzero value, except that the returned pointer shall
not be used to access an object.

Then the ??alloc() functions are described in 7.20.3.* .

Does the above quote's "either, or" apply to all the ??alloc() functions
*together* or *separately*?

Example:
In GNU libc malloc(0)!=NULL, but realloc(..., 0)==NULL. Is this
compliant?

TIA

--
Stan Tobias
 
Reply With Quote
 
 
 
 
Stephen Sprunk
Guest
Posts: n/a
 
      05-17-2004
<(E-Mail Removed)> wrote in message news:(E-Mail Removed)...
>
> 7.20.3#1
> [...] If the size of the space requested is
> zero, the behavior is implementation-defined: either a null
> pointer is returned, or the behavior is as if the size were
> some nonzero value, except that the returned pointer shall
> not be used to access an object.
>
> Then the ??alloc() functions are described in 7.20.3.* .
>
> Does the above quote's "either, or" apply to all the ??alloc() functions
> *together* or *separately*?
>
> Example:
> In GNU libc malloc(0)!=NULL, but realloc(..., 0)==NULL. Is this
> compliant?


realloc(ptr, 0) is defined to be equal to free(ptr) and return NULL.

Since the 'either' doesn't make sense in the case of realloc(), the logical
conclusion is that the non-NULL return is allowed for malloc() independently
of how realloc() behaves.

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin

 
Reply With Quote
 
 
 
 
sNOiSPAMt@amu.edu.pl
Guest
Posts: n/a
 
      05-17-2004
Stephen Sprunk <(E-Mail Removed)> wrote:
> realloc(ptr, 0) is defined to be equal to free(ptr) and return NULL.


No, it's nowhere defined like that. It's not even equivalent of free()
(google for "realloc equivalent free"), although it may be implemented
this way.

In C89 there is a clause: " If size is zero and ptr is not a null
pointer, the object it points to is freed.", but this does not mean
that realloc(..., 0) merely performs free(); IMO it requires realloc()
to free the original buffer irrespective of whether subsequent zero-sized
allocation succeeds or not (in opposition to non-zero size reallocation,
where the original buffer cannot change on failure). Both C89 and C99
agree on that, only they're differently worded.

In general, not freeing realloc(..., 0) result leads to memory leak.

> Since the 'either' doesn't make sense in the case of realloc(), the logical
> conclusion is that the non-NULL return is allowed for malloc() independently
> of how realloc() behaves.


Provided your assumption was wrong, the conclusion is irrelevant.
But my question equally might apply to malloc()/calloc() implementation.
So, can malloc(0)==NULL and calloc(0,0)!=NULL ?

--
Stan Tobias
 
Reply With Quote
 
Arthur J. O'Dwyer
Guest
Posts: n/a
 
      05-17-2004

On Mon, 17 May 2004 http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
>
> In general, not freeing realloc(..., 0) result leads to memory leak.


Correct. Implementations are allowed to return NULL from
realloc(..., 0), in which case the free() does nothing; but they
are also allowed to return not-NULL, in which case the free() is
required.

> But my question equally might apply to malloc()/calloc() implementation.
> So, can malloc(0)==NULL and calloc(0,0)!=NULL ?


Sure. Do you have any reason to suspect otherwise? [In
practice, this will never happen; it's purely a QoI issue.]

-Arthur
 
Reply With Quote
 
sNOiSPAMt@amu.edu.pl
Guest
Posts: n/a
 
      05-18-2004
Arthur J. O'Dwyer <(E-Mail Removed)> wrote:

> On Mon, 17 May 2004 (E-Mail Removed) wrote:
>> But my question equally might apply to malloc()/calloc() implementation.
>> So, can malloc(0)==NULL and calloc(0,0)!=NULL ?


> Sure. Do you have any reason to suspect otherwise? [In


Yes, reading 7.20.3 in n869.txt, indeed I do.

All sentences in 7.20.3#1 apply equally to all ??alloc() fns. Further,
"Each such allocation shall yield a pointer to an object disjoint from
any other object." applies to the *whole group* of ??alloc() fns (ie. I
need not worry that malloc() and calloc() might overlap). I don't see why
"If the size of the space requested is zero, [...]" should have different
context; if it was meant to have, the unambiguous way to express this
would be to repeat this clause at each ??alloc() description.

BTW, I don't understand the last sentence there: "The value of a pointer
that refers to freed space is indeterminate."; where does it apply to?

> practice, this will never happen; it's purely a QoI issue.]


Well, it does happen to malloc() vs. realloc(). What I mean to say,
is that no QoI shall save me any work for portable code.

The practical difference is for strict error detection. If for zero
allocation size return value may differ for each ??alloc(), then I have
to write different error-checking code for each of them.

For example:

#if MALLOC_0_NULL
# define malloc_error(ret, size) (ret == NULL && size > 0)
#else
# define malloc_error(ret, size) (ret == NULL)
#endif

#if CALLOC_0_NULL
# define calloc_error(ret, nmemb, size) (ret == NULL && nmemb > 0 && size > 0)
#else
# define calloc_error(ret, nmemb, size) (ret == NULL)
#endif

#if REALLOC_PTR_0_NULL
# define realloc_error(ret, ptr, size) \
(ptr == NULL ? malloc_error(ret, size) : ret == NULL && size > 0)
#else
# define realloc_error(ret, ptr, size) \
(ptr == NULL ? malloc_error(ret, size) : ret == NULL)
#endif

(I wrote those from scratch, hope there's no error)

MALLOC_0_NULL, CALLOC_0_NULL, REALLOC_PTR_0_NULL have to be known for
every implementation; there seems to be no "general" solution, ie.
without knowing them.

--
Stan Tobias
 
Reply With Quote
 
Jack Klein
Guest
Posts: n/a
 
      05-18-2004
On 17 May 2004 16:58:48 GMT, (E-Mail Removed) wrote in
comp.lang.c:

>
> 7.20.3#1
> [...] If the size of the space requested is
> zero, the behavior is implementation-defined: either a null
> pointer is returned, or the behavior is as if the size were
> some nonzero value, except that the returned pointer shall
> not be used to access an object.
>
> Then the ??alloc() functions are described in 7.20.3.* .
>
> Does the above quote's "either, or" apply to all the ??alloc() functions
> *together* or *separately*?
>
> Example:
> In GNU libc malloc(0)!=NULL, but realloc(..., 0)==NULL. Is this
> compliant?
>
> TIA


I've seen several replies and your responses in this thread, so I'll
just add three points:

1. Since the behavior is implementation-defined, you should consult
the implementation's required documentation.

2. The proper place to ask for definitive interpretation of the
wording of the standard is news:comp.std.c, not here. Several members
of the standards committees read and respond there regularly.

3. N869 is not the standard, and the wording you quote (farther down
the thread, I admit) is no longer where you found it. It has moved
somewhere else. But the statement that freeing a pointer renders it
indeterminate merely provides a way of stating that any use of its
value, even if not to dereference, produces undefined behavior, as
does the use of any indeterminate value.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
 
Reply With Quote
 
Arthur J. O'Dwyer
Guest
Posts: n/a
 
      05-18-2004

On Mon, 18 May 2004 (E-Mail Removed) wrote:
>
> Arthur J. O'Dwyer <(E-Mail Removed)> wrote:
> > On Mon, 17 May 2004 (E-Mail Removed) wrote:
> > >
> > > So, can malloc(0)==NULL and calloc(0,0)!=NULL ?

> >
> > Sure. Do you have any reason to suspect otherwise? [In

>
> Yes, reading 7.20.3 in n869.txt, indeed I do.


[I'm reading N869, too, BTW. I don't have a copy of the Standard.]

> All sentences in 7.20.3#1 apply equally to all ??alloc() fns. Further,
> "Each such allocation shall yield a pointer to an object disjoint from
> any other object." applies to the *whole group* of ??alloc() fns (ie. I
> need not worry that malloc() and calloc() might overlap).


Naturally.

> I don't see why "If the size of the space requested is zero, [...]"
> should have different context; if it was meant to have, the unambiguous
> way to express this would be to repeat this clause at each ??alloc()
> description.


Suppose the implementation's default behavior upon malloc(0) is to
return a newly allocated chunk of memory containing no payload -- just
a header and footer (speaking from the POV of the malloc implementor,
not the C programmer). Now suppose I write

while (1) {
if (malloc(0) == NULL) break;
}
puts("malloc returned NULL");

Do you see now that at some point 'malloc(0)' *MUST* return NULL,
no matter what it normally returns?
Since we don't know when the system will run out of free memory,
we can never say with certainty when 'malloc' (or 'calloc') will
return NULL.


> BTW, I don't understand the last sentence there: "The value of a pointer
> that refers to freed space is indeterminate."; where does it apply to?


free(p);
/* p is now indeterminate, and its value must not be used */
See the recent thread in Google Groups' archives if you still have
questions. This is a RAQ (Recently Asked Question).


> > practice, this will never happen; it's purely a QoI issue.]

>
> Well, it does happen to malloc() vs. realloc(). What I mean to say,
> is that no QoI shall save me any work for portable code.


I meant: If any real implementation made the following code
print "Yes", then that real implementation would be considered to
have a poor "Quality of Implementation."

#include <stdio.h>
#include <stdlib.h>
int main(void) {
if (malloc(0) != NULL) return 0;
if (calloc(0,0) == NULL) return 0;
puts("Yes");
}

As for "portability," this has little to do with it. See below.

> The practical difference is for strict error detection. If for zero
> allocation size return value may differ for each ??alloc(), then I have
> to write different error-checking code for each of them.
>
> For example:
>
> #if MALLOC_0_NULL
> # define malloc_error(ret, size) (ret == NULL && size > 0)
> #else
> # define malloc_error(ret, size) (ret == NULL)
> #endif


Simply '#define malloc_error(ret,size) (ret == NULL)' and then
make sure to error-check the input to 'malloc' so that you never
pass 0 to 'malloc' to begin with. If you're dealing with legacy
code, rather than writing your own, you can always put

#define safe_malloc(b) malloc((b)+1) /* guaranteed nonzero */
#define malloc_error(p, z) (0 == (p)) /* NULL return from malloc */

and then do a search-and-replace of 'malloc' by 'safe_malloc'.
But that's a very silly way to ensure portability. It would be
much better to write sensible, non-zero-allocating code in the
first place.

> MALLOC_0_NULL, CALLOC_0_NULL, REALLOC_PTR_0_NULL have to be known for
> every implementation; there seems to be no "general" solution, ie.
> without knowing them.


The general solution is to write code that doesn't depend on
quirks or corner cases in the implementation.

HTH,
-Arthur

 
Reply With Quote
 
sNOiSPAMt@amu.edu.pl
Guest
Posts: n/a
 
      05-18-2004
Arthur J. O'Dwyer <(E-Mail Removed)> wrote:

> [I'm reading N869, too, BTW. I don't have a copy of the Standard.]


Prompted by Jack Klein's answer, I've finally bought the C99 Standard
myself. Indeed, the wording differs slightly from n869.txt, but it
chages nothing in the discussion.


[snip]
>
> while (1) {
> if (malloc(0) == NULL) break;
> }
> puts("malloc returned NULL");
>
> Do you see now that at some point 'malloc(0)' *MUST* return NULL,
> no matter what it normally returns?


But that's an error return, right? All I was saying was in the case
of *successful* return.


> > BTW, I don't understand the last sentence there: "The value of a pointer
> > that refers to freed space is indeterminate."; where does it apply to?

>

[snip]
> questions. This is a RAQ (Recently Asked Question).


I'm sorry. I remember even seeing that discussion in my news-reader.
Thank you for pointing this out to me, I'll read it later.


> > > practice, this will never happen; it's purely a QoI issue.]

> >
> > Well, it does happen to malloc() vs. realloc(). What I mean to say,
> > is that no QoI shall save me any work for portable code.

>
> I meant: If any real implementation made the following code
> print "Yes", then that real implementation would be considered to
> have a poor "Quality of Implementation."

[snipped code]

Yes, I agree it would be absurd if malloc(0)!=calloc(0,0). What I wanted
to point out is that from my POV it might be considered equally absurd
that malloc(0)!=realloc(p,0). realloc(p,0) is not free(p), it "allocates"
zero-sized buffer, same way as malloc(0) does. If my interpretation
was right, then there wouldn't be such asymmetry between strict error
checking for malloc() and realloc():

/* works for all ??alloc()s */
#if ALLOC_0_NULL
# define alloc_error(ret, size) (ret != NULL && size > 0)
#else
# define alloc_error(ret, size) (ret != NULL)
#endif

> Simply '#define malloc_error(ret,size) (ret == NULL)' and then
> make sure to error-check the input to 'malloc' so that you never
> pass 0 to 'malloc' to begin with. If you're dealing with legacy
> code, rather than writing your own, you can always put
>
> #define safe_malloc(b) malloc((b)+1) /* guaranteed nonzero */
> #define malloc_error(p, z) (0 == (p)) /* NULL return from malloc */
>
> and then do a search-and-replace of 'malloc' by 'safe_malloc'.
> But that's a very silly way to ensure portability. It would be
> much better to write sensible, non-zero-allocating code in the
> first place.


One way or another, you have to end up writing your own wrapper library
(that does not even have to depend on the implementation!), which renders
the Standard somewhat "useless"

Another way is to only check for:
#define alloc_error(ret, size) (ret == NULL && size > 0)
ie. always assume malloc(0)==NULL convention. This is what I call relaxed
error checking, and will work when malloc(0)!=NULL (if the rest of the
code is portable, it must be prepared for accepting NULL and won't depend
on distinct returned pointers).

What I want for now is a portable (by that I understand correct wrt Std)
code that works with Standard Library; I want to know what the Standard
actually says, and what is deviation from it. The second motivation
is simply curiosity.

Thank you for your answers. Encouraged by Jack Klein (I thank him too)
I'm going to re-ask this question in CSC.

--
Stan Tobias
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
/usr/bin/ld: ../../dist/lib/libjsdombase_s.a(BlockGrouper.o)(.text+0x98): unresolvable relocation against symbol `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostre silverburgh.meryl@gmail.com C++ 3 03-09-2006 12:14 AM
error: 'std::ios_base& std::ios_base::operator=(const std::ios_base&)' is private Geoffrey S. Knauth C++ 6 01-18-2006 11:48 AM
xServices::CServices<TImp>::StHoldClientList::StHoldClientList(std::set<TImp*, std::less<TImp*>, std::allocator<TImp*> >&)': Vinu C++ 4 07-07-2005 06:08 AM
xServices::CServices<TImp>::StHoldClientList::StHoldClientList(std::set<TImp*, std::less<TImp*>, std::allocator<TImp*> >&)': Vinu C++ 0 07-06-2005 12:45 PM
std::map<int,std::set<std::string> > Wrong? (Segmentation fault.) Peter Jansson C++ 5 03-17-2005 06:34 AM



Advertisments