167

I just saw this code:

artist = (char *) malloc(0); 

...and I was wondering why would one do this?

1

16 Answers 16

164

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; 
Sign up to request clarification or add additional context in comments.

11 Comments

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.
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.
Really wish the specs would say "safely passed to realloc" as well -.-
@NSAddict "empty struct where sizeof will return 0", please provide an example, sounds like a language extension.
@hanshenrik Who says you can't? realloc() allows you to pass any valid pointer returned by malloc(). Should be enough.
|
64

The C standard (C17 7.22.3/1) 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.

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.

8 Comments

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.
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.
Since the circumstances of malloc failure to obtain memory are implementation-defined, an implementation could simply define that size-0 allocations are always unsatisfiable (ENOMEM), and now malloc(0) returning 0 (with errno==ENOMEM) is consistent. :-)
Can you realloc a pointer returned by malloc(0)? Can you realloc((char*)NULL)?
@Braden Best Yes to both.
|
16

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.

9 Comments

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.
Malloc implementations perform record keeping which could add a certain amount of data per pointer returned on top of the size requested.
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.
The library can do whatever it wants - well, it can either return a unique pointer that no other malloc() will return, or return NULL.
@jldupont: At least the Microsoft C Run-Time library returns a unique pointer for malloc(0). However, in the very same implementation of the standard C library, realloc(ptr, 0) frees ptr and returns NULL.
|
8

There's an answer elsewhere on this page that begins "malloc(0) will return a valid memory address and whose range will depend on the type of pointer which is being allocated memory". This statement is incorrect (I don't have enough reputation to comment on that answer directly, so can't put this comment directly under there).

Doing malloc(0) will not automatically allocate memory of correct size. The malloc function is unaware of what you're casting its result to. The malloc function relies purely on the size number that you give as its argument. You need to do malloc(sizeof(int)) to get enough storage to hold an int, for example, not 0.

Comments

7

There are a lot of half true answers around here, so here are the hard facts. The man-page for malloc() says:

If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().

That means, there is absolutely no guarantee that the result of malloc(0) is either unique or not NULL. The only guarantee is provided by the definition of free(), again, here is what the man-page says:

If ptr is NULL, no operation is performed.

So, whatever malloc(0) returns, it can safely be passed to free(). But so can a NULL pointer.

Consequently, writing artist = malloc(0); is in no way better than writing artist = NULL;

3 Comments

Too bad the implementation isn't allowed to return a non-null, non-unique pointer. That way, malloc(0) could return, say, 0x1, and free() could have a special-case check of 0x1 just as it has for 0x0.
man may as well document the implementation-defined form used in *nix. In this case it doesn't, but it still isn't a canonical source for general C.
@Lundin True. But the man-pages are much more accessible than the C standard, and the man-pages on GNU/Linux systems generally document quite well which standard(s) the implementation follows. Along with information of which parts adhere to which standard, should they differ. I have the feeling that they both want to be precise, and advertise every single bit that's a GNU extension...
4

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.

Comments

4

Why you shouldn't do this...

Since malloc's return value is implementation dependent, you may get a NULL pointer or some other address back. This can end up creating heap-buffer overflows if error handling code doesn't check both size and returned value, leading to stability issues (crashes) or even worse security issues.

Consider this example, where further accessing memory via returned address will corrupt heap iff size is zero and implementation returns a non NULL value back.

size_t size; /* Initialize size, possibly by user-controlled input */ int *list = (int *)malloc(size); if (list == NULL) { /* Handle allocation error */ } else { /* Continue processing list */ } 

See this Secure Coding page from CERT Coding Standards where I took the example above for further reading.

Comments

2

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.

Comments

1

In Windows:

  • void *p = malloc(0); will allocate a zero-length buffer on the local heap. The pointer returned is a valid heap pointer.
  • malloc ultimately calls HeapAlloc using the default C runtime heap which then calls RtlAllocateHeap, etc.
  • free(p); uses HeapFree to free the 0-length buffer on the heap. Not freeing it would result in a memory leak.

Comments

1

The person who wrote the code likely wants you to think of malloc(0) as an empty initialized array to which values are to be added (realloc()). While this works regardless of whether malloc(0) returns NULL or an actual pointer, it spawns ground for misunderstanding:

Without implementation-awareness, you won't be able to tell what a potential NULL returned by malloc(0) means. It could mean that you are out of memory, but it could also mean that that's what the implementation decides to return for allocations of size 0. Even if this is inconsequential to what your code does, it can raise some eyebrows.

This means that malloc(0) is an attempt at writing more readable code. However, due the fact that it engages implementation-specific behavior, losing information in the process, it is likely to cause confusion instead. Do not use it unless you specifically require the result of the implementation-specific behavior.

3 Comments

So how do you portably handle checking for failure if you call malloc(0)? if you use malloc(0) at all, malloc() returning NULL loses all special meaning as an error condition. That's the exact opposite of "higher-level language programmer" - your code lost information and you now have to write extra code to paper over that.
This seems like a bad idea. Using malloc(0) like this is un-idiomatic. I'm not sure what the point of "deflects responsibility" is; using the result of malloc(0) doesn't exactly assign a proper value any more than assigning NULL (less so since the assigned value is implementation-defined for malloc(0)), and certainly it deflects the responsibility of checking for allocation errors to a possible later call to realloc. I don't see anything "higher-level" about this; it seems like a mess.
I have rewritten my answer to reflect your criticism. Please mind I want the answer to stand out in that it pictures a line of reasoning based on developer idiosyncrasy rather than what the code actually does.
0

To actually answer the question made: there is no reason to do that

Comments

0

There are some benefits to get a valid pointer from malloc(0):

  1. To separate malloc(0) from malloc(request too much memory), which actually return NULL.
  2. If malloc(0) is valid pointer, that obligate you to call free for it. There is the scenario when you forget to call free after allocation some memory, and the size of requested memory could be 0, in this situation when malloc(0) returns NULL when you launch program with sanitizers everything will be fine, but if malloc(0) returns valid pointer when you launch program with memory sanitizers you will fault, so malloc(0) -> valid pointer make process of searching errors easier.
  3. if malloc(0) is valid pointer, it makes malloc return code unique, so you can use the result of it as unique identifier of object, which can be useful on some cases.

Comments

-2

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

Comments

-2

Its actually quite useful, and (obviously IMHO), the allowed behavior of returning a NULL pointer is broken. A dynamic pointer is useful not only for what it points at, but also the fact that it's address is unique. Returning NULL removes that second property. All of the embedded mallocs I program (quite frequently in fact) have this behavior.

3 Comments

Could you give an example of when this is useful?
So why don't you malloc(1) then? That would return a unique address (at least unique within the lifetime of the allocated object).
PS: I doubt that your use case was a realistic use case in the time that malloc was "invented".
-3

malloc(0) will return NULL or a valid pointer which can be rightly passed to free. And though it seems like the memory that it points to is useless or it can't be written to or read from, that is not always true. :)

int *i = malloc(0); *i = 100; printf("%d", *i); 

We expect a segmentation fault here, but surprisingly, this prints 100! It is because malloc actually asks for a huge chunk of memory when we call malloc for the first time. Every call to malloc after that, uses memory from that big chunk. Only after that huge chunk is over, new memory is asked for.

Use of malloc(0): if you are in a situation where you want subsequent malloc calls to be faster, calling malloc(0) should do it for you (except for edge cases).

5 Comments

Writing to *i may not crash in your case, but it's undefined behavior nevertheless. Watch out for nasal demons!
Yes. That is true. It is implementation specific. I have verified it on MaxOS X and some Linux distribution. I have not tried it on other platforms. Having said that, the concept that I have described has been described in the book "The C programming language" by Brain Kernighan and Dennis Ritchie.
I know: super late comment on this question. But there is sometimes a use for malloc(0) that isn't mentioned. On those implementations where it returns a non-NULL value, especially in a DEBUG build, it likely allocates MORE than you asked for, and gives you the pointer to just past its internal header. This allows you to get a feel for actual memory usage if you get this before and after a series of allocations. e.g.: void* before = malloc(0); ... void* after = malloc(0); long long total = after - before; or some such.
I read "The C programming language" by Brain Kernighan and Dennis Ritchie and I don't remember it saying anything about malloc(0). Could you please say which chapter are you referring too? Providing an exact quote would be nice too.
but surprisingly, this prints 100! Ouch. And how do you know your simple toy program didn't corrupt the heap in a way that won't be apparent in a program that immediately exits after the assignment to an invalid pointer?
-3

Here is the analysis after running with valgrind memory check tool.

==16740== Command: ./malloc0 ==16740== p1 = 0x5204040 ==16740== ==16740== HEAP SUMMARY: ==16740== in use at exit: 0 bytes in 0 blocks ==16740== total heap usage: 2 allocs, 2 frees, 1,024 bytes allocated ==16740== ==16740== All heap blocks were freed -- no leaks are possible 

and here's my sample code:

#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { //int i; char *p1; p1 = (char *)malloc(0); printf("p1 = %p\n", p1); free(p1); return 0; } 

By default 1024 bytes is allocated. If I increase the size of malloc, the allocated bytes will increase by 1025 and so on.

1 Comment

its implementation dependant

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.