tags:

views:

929

answers:

7

Just saw this code:

artist = (char*)malloc(0);

and I was wondering why would one do this?

+22  A: 

According to the specifications, malloc(0) will return either "a null pointer or a unique pointer that can be successfully passed to free()".

This basically lets you allocate nothing, but still pass the "artist" variable to a call to free() without worry. For practical purposes, it's pretty much the same as doing:

artist = NULL;
Reed Copsey
that's what I had guessed. Would this constitute a good "cross-platform" strategy?
jldupont
Personally, I think setting to NULL is a better cross-platform strategy, since free() is guaranteed (by spec) to work fine on NULL as input.
Reed Copsey
As mentioned by C. Ross, some platforms, technically, could return a pointer here (that is a "unique pointer that can be passed to free"), but if you're treating this as a char*, that may give you an invalid, non-terminated char. It could be dangerous to rely on this in cross-platform situations.
Reed Copsey
@Reed: many thanks for your contribution.
jldupont
+1  A: 

Not sure, according to some random malloc source code I found, an input of 0 results in a return value of NULL. So it's a crazy way of setting the artist pointer to NULL.

http://www.raspberryginger.com/jbailey/minix/html/lib_2ansi_2malloc_8c-source.html

Doug T.
+5  A: 

The C standard says:

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

So, malloc(0) could return NULL or a valid pointer that may not be dereferenced. In either case, it's perfectly valid to call free() on it.

I don't really think malloc(0) has much use, except in cases when malloc(n) is called in a loop for example, and n might be zero.

Looking at the code in the link, I believe that the author had two misconceptions:

  • malloc(0) returns a valid pointer always, and
  • free(0) is bad.

So, he made sure that artist and other variables always had some "valid" value in them. The comment says as much: // these must always point at malloc'd data.

Alok
The fact that it is implementation dependent makes it more or less completely useless - this is one of the crappier bits of the C standard, and quite a few of the standards comittee (for example P.J. Plauger) have moaned about it.
anon
I agree. If `malloc(0)` returned a valid pointer, then `malloc()` returning `NULL` means "failure" always, and `0` isn't a special case anymore, which is more consistent.
Alok
+1  A: 

Possibly it is so you can realloc() it later?

realloc on a possibly NULL pointer?
jldupont
Nope, still pointless. It's fine to realloc a NULL pointer: `realloc(NULL, n)` is defined to do the same thing as `malloc(n)`. It's sometimes even useful, if you're resizing an array to be "big enough", then you don't have to special-case the first allocation, you can just start with a NULL pointer and size 0, and realloc from there.
Steve Jessop
`realloc(NULL, size)` is equivalent to `malloc(size)`.
Alok
+3  A: 

malloc(0) behaviour is implementation specific. The library can return NULL or have the regular malloc behaviour, with no memory allocated. Whatever it does, it must be documented somewhere.

Usually, it returns a pointer that is valid and unique but should NOT be dereferenced. Also note that it CAN consume memory even though it did not actually allocate anything.

It is possible to realloc a non null malloc(0) pointer.

Having a malloc(0) verbatim is not much use though. It's mostly used when a dynamic allocation is zero byte and you didn't care to validate it.

Coincoin
`malloc()` must keep "housekeeping information" somewhere (this size of the block allocated for example, and other auxiliary data). So, if `malloc(0)` does not return `NULL`, it will use memory to store that information, and if not `free()`d, will constitute a memory leak.
Alok
Malloc implementations perform record keeping which could add a certain amount of data per pointer returned on top of the size requested.
sixlettervariables
Memory consumed and memory allocated does not mean the same thing. In this very case, most implementation will return a unique pointer. This mean a part of the address space needs to be sacrificed for that pointer. Depending on the allocator, this might actually mean it will allocate 1 byte or more.
Coincoin
@jldupont: In practice if an implementation does take this option, then it's because it has gone through all the motions of doing an allocation, but with size 0. The overhead will be the same as for any other allocation. Even if it did something different, it would still have to reserve some address space, and make a record somewhere that it has done so.
Steve Jessop
@Steve: of course... but which implementation would do this anyways?
jldupont
*The library can do whatever it wants* - well, it can either return a unique pointer that no other `malloc()` will return, or return `NULL`.
Alok
@jldupont: you want a list of memory allocators which return non-NULL for `malloc(0)`? I don't know, sorry, it's not something I've ever felt the need to rely on. I wouldn't consider it unreasonable, though: returning NULL in this case is basically an early-out speed optimisation, for a case that probably never happens. Waste of good ASCII characters, unless your allocation code would special-case 0 anyway.
Steve Jessop
@Steve: I was just curious, that's all. Thanks.
jldupont
@Alok: Thanks, fixed.
Coincoin
+3  A: 

malloc(0) doesn't make any sense to me, unless the code is relying on behaviour specific to the implementation. If the code is meant to be portable, then it has to account for the fact that a NULL return from malloc(0) isn't a failure. So why not just assign NULL to artist anyway, since that's a valid successful result, and is less code, and won't cause your maintenance programmers to take time figuring it out?

malloc(SOME_CONSTANT_THAT_MIGHT_BE_ZERO) or malloc(some_variable_which_might_be_zero) perhaps could have their uses, although again you have to take extra care not to treat a NULL return as a failure if the value is 0, but a 0 size is supposed to be OK.

Steve Jessop
@steve: thanks for your thoughts.
jldupont
+2  A: 

Admittedly, I have never seen this before, this is the first time I've seen this syntax, one could say, a classic case of function overkill. In conjunction to Reed's answer, I would like to point out that there is a similar thing, that appears like an overloaded function realloc:

  • foo is non-NULL and size is zero, realloc(foo, size);. When you pass in a non-NULL pointer and size of zero to realloc, realloc behaves as if you’ve called free(…)
  • foo is NULL and size is non-zero and greater than 1, realloc(foo, size);. When you pass in a NULL pointer and size is non-zero, realloc behaves as if you’ve called malloc(…)

Hope this helps, Best regards, Tom.

tommieb75