call to malloc with size 0

N

Neo

Hi Folks,

I've a simple qestion related to dynamic memory allocation in C here is the
code:

#include <stdio.h>

int main()

{

char *p;

if( (p=(char*)malloc(0)) == NULL)

printf("NULL\n");

else

printf("Valid Pointer\n");

return 0;

}



Output : "Valid Pointer"

Why this code fragment returns a valid pointer to a memory block???

-Neo
 
P

Peter Smithson

Why this code fragment returns a valid pointer to a memory block???

-Neo

I've seen this before. Some versions of UNIX will return an error,
others will return a valid pointer. I'm not sure which is correct but I
found the 2nd situation to be more common and more useful as you don't
have to code round it - I've got a few +1's in some code just to
guarentee a valid pointer which happens to contain nothing. That way I
know the pointer has been initialised even it doesn't contain anything.
It's working like a flag as well as a place to store results.
 
R

Ravi Uday

Neo said:
Hi Folks,

I've a simple qestion related to dynamic memory allocation in C here is the
code:

#include <stdio.h>

int main()

{

char *p;

if( (p=(char*)malloc(0)) == NULL)

printf("NULL\n");

else

printf("Valid Pointer\n");

return 0;

}



Output : "Valid Pointer"

Why this code fragment returns a valid pointer to a memory block???

-Neo
See what the standard says

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.

So check in your impelementation documents for answer !

- Ravi
 
N

Neo

Ravi Uday said:
See what the standard says

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.

So check in your impelementation documents for answer !

- Ravi

O'kay thanks for pointing it out.
But what should be the suggested behavior and why?
Is a valid pointer right way?
I think NULL is a better option? isn't it???

-Neo
 
L

Lawrence Kirby

Get rid of the cast. The compiler should then complain, which is
good because the code is broken. Adding the cast doesn't fix the
code, it just stops the compiler complaining about the problem.

The problem is that you don't have a valid declaration for malloc()
in scope when you call it. In that case the compiler assumes
that malloc() returns int, but it doesn't, it returns void *. All
standard library functions are provided with a declaration in

Your code invokes undefined behaviour due to the invalid cast, so anything
can happen. Once that's fixed the issue is as below i.e. the compiler does
it because the standard says it can.
See what the standard says

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.

So check in your impelementation documents for answer !

Lawrence
 
M

Method Man

Ravi Uday said:
See what the standard says

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.

So check in your impelementation documents for answer !

- Ravi

<OT>

Why didn't they put it in the standard that a null pointer must be returned?
It seems like the right/logical behaviour for calling malloc on size 0 and
avoids any confusion.

</OT>
 
R

Richard Bos

Peter Smithson said:
I've seen this before. Some versions of UNIX will return an error,

By which, I hope, you mean a null pointer, since causing a segfault or a
signal for malloc(0) is not conforming.
others will return a valid pointer. I'm not sure which is correct

Either.

Richard
 
L

Lawrence Kirby

On Wed, 17 Nov 2004 07:45:50 -0500, Method Man wrote:


....
<OT>

Why didn't they put it in the standard that a null pointer must be returned?
It seems like the right/logical behaviour for calling malloc on size 0 and
avoids any confusion.

</OT>

Probably because there were existing implementations for both types of
result. I don't think it makes much practical difference, I can only think
of 2 uses for this:

1. Creating a unique pointer value which compares unequal to all others.
For this to work you would need to prefer the non-null return behaviour.
Of course you can use malloc(1) for this. However malloc() can always fail
so it could return null for any call.

2. You are setting up an object whick you might extend later using
realloc(). However whether malloc(0) return null or not is immaterial to
this, either result can be passed to realloc(). So the latitude given by
the standard is harmless here. Of course you have the issue of freeing the
"object" for a non-null return.

Lawrence
 
R

Richard Bos

Lawrence Kirby said:
2. You are setting up an object whick you might extend later using
realloc(). However whether malloc(0) return null or not is immaterial to
this, either result can be passed to realloc(). So the latitude given by
the standard is harmless here. Of course you have the issue of freeing the
"object" for a non-null return.

Even that is not a problem, since free(0) is harmless. No matter what
you get from malloc(), you can free() it.

Richard
 
L

Lawrence Kirby

Even that is not a problem, since free(0) is harmless. No matter what
you get from malloc(), you can free() it.

True, my intent was more along the lines of you have consider calling free()
appropriately for a non-null return, whereas if the return was always
null in this case you wouldn't have to worry.

However given the possibility extending the object to non-zero length
there's likely to be code to handle freeing anyway, so it probably turns
out to be a non-issue.

Lawrence
 
N

Neo

Lawrence Kirby said:
Get rid of the cast. The compiler should then complain, which is
good because the code is broken. Adding the cast doesn't fix the
code, it just stops the compiler complaining about the problem.

The problem is that you don't have a valid declaration for malloc()
in scope when you call it. In that case the compiler assumes
that malloc() returns int, but it doesn't, it returns void *. All
standard library functions are provided with a declaration in


Your code invokes undefined behaviour due to the invalid cast, so anything
can happen. Once that's fixed the issue is as below i.e. the compiler does
it because the standard says it can.

invalid cast - what do you mean by saying *invalid cast*. isnt it a standard
practice to cast the pointer returned by the malloc() to desired type? or
how then it can be otherwise like:
p = malloc(0);
???
 
E

E. Robert Tisdale

Neo said:
I've a simple qestion related to dynamic memory allocation in C.
[snip]

> cat main.c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[]) {

char *p = (char*)malloc(0);

if(NULL == p)
printf("NULL\n");
else
printf("Valid Pointer\n");

printf("*((int*)p - 1) = %d\n", *((int*)p - 1));
printf("p = %p\n", p);
return EXIT_SUCCESS;
}
> gcc -Wall -std=c99 -pedantic -o main main.c
> ./main
Valid Pointer
*((int*)p - 1) = 17
p = 0x9876008

My implementation allocates at least two
double word aligned double words
and returns a pointer to the second double word.
Why this code fragment returns a valid pointer to a memory block?

Because it can.
 
P

pete

isnt it a standard
practice to cast the pointer returned by the malloc() to desired type?

No.
It's a mistake that people make when they neglect to include stdlib.h,
and the compiler consequently warns them that malloc is returning
type int and needs to be cast.
Add
#include <stdlib.h>
and drop the cast.
 
M

Method Man

Lawrence Kirby said:
On Wed, 17 Nov 2004 07:45:50 -0500, Method Man wrote:


...


Probably because there were existing implementations for both types of
result. I don't think it makes much practical difference, I can only think
of 2 uses for this:

1. Creating a unique pointer value which compares unequal to all others.
For this to work you would need to prefer the non-null return behaviour.
Of course you can use malloc(1) for this. However malloc() can always fail
so it could return null for any call.

Fair enough. Although, I can't immediately see a practical use in obtaining
a valid pointer from malloc(0). I would be curious to know how the
implementation handled dereferencing and type-casting for this magical
pointer.
 
D

Dan Pop

Fair enough. Although, I can't immediately see a practical use in obtaining
a valid pointer from malloc(0).

It's a "cheap" method for generating unique IDs.
I would be curious to know how the
implementation handled dereferencing and type-casting for this magical
pointer.

The pointer is as ordinary as you can get. Dereferencing it invokes
undefined behaviour and conversions work as for other pointers. As
Lawrence told you, if you need this particular behaviour, just use the
following wrapper for malloc:

void *xmalloc(size_t size)
{
if (size == 0) size = 1;
return malloc(size);
}

And if you need the other behaviour, you can trivially get it from:

void *ymalloc(size_t size)
{
if (size == 0) return NULL;
return malloc(size);
}

Or, if you prefer macros:

#define XMALLOC(size) malloc(size == 0 ? 1 : size)
#define YMALLOC(size) (size == 0 ? NULL : malloc(size))

Dan
 
J

Joona I Palaste

Fair enough. Although, I can't immediately see a practical use in obtaining
a valid pointer from malloc(0). I would be curious to know how the
implementation handled dereferencing and type-casting for this magical
pointer.

If the C memory model was continuous rather than discrete, then there
would be no problem. In a continuous memory model, pointer values would
only serve as "starting points" of allocated memory, not allocated
memory itself. If you think of the conventional discrete memory model as
labelling boxes with addresses, in a continuous memory model you don't
label the boxes, you label the gaps between them. This way the malloc()
implementation could safely return the same, non-null, pointer value
over and over again from calls to malloc(0), because reserving 0 bytes
onward from that gap between boxes doesn't actually reserve any box at
all, and it's the boxes you store stuff in, not the gaps between them.
This is of course very much off-topic for comp.lang.c but those who
have studied real analysis and topology know what I'm talking about.
 
C

Craig Barkhouse

Dan Pop said:
It's a "cheap" method for generating unique IDs.

Are successive calls to malloc(0) guaranteed to return unique values,
though? (Assuming they don't return NULL.) Given that actually
dereferencing such the pointer invokes undefined behaviour, couldn't a
malloc() implementation set aside a certain value that it always returns
when size is 0? It might have to increment a reference count that would
later get decremented by free().
 
R

Richard Bos

Craig Barkhouse said:
Are successive calls to malloc(0) guaranteed to return unique values,
though? (Assuming they don't return NULL.) Given that actually
dereferencing such the pointer invokes undefined behaviour, couldn't a
malloc() implementation set aside a certain value that it always returns
when size is 0?

In C89, it isn't perfectly clear; the text says that

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

without clarifying whether that means a pointer unique to zero-sized
malloc()s, or a unique pointer for _each_ zero-sized malloc().

In C99, this has been changed to

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

Since

# Each such allocation shall yield a pointer to an object disjoint from
# any other object.

this means that in C99, each zero-sized malloc() must return a distinct
pointer (or a null pointer), and I think that with this knowledge, it's
clear that this was what was meant in C89, too.

Richard
 
B

Ben Pfaff

Method Man said:
I can't immediately see a practical use in obtaining a valid
pointer from malloc(0). I would be curious to know how the
implementation handled dereferencing and type-casting for this
magical pointer.

Dereferencing the result of malloc(0) yields undefined behavior.
What problem do you envision with type-casting it?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top