If `malloc (0)` returns a non-zero pointer, can I pass this `free`?

I read a discussion of how malloc behaves when you request a block with a zero size.

I understand that the behavior of malloc(0) is determined by the implementation, and it is supposed to either return a null pointer or a non-zero pointer, which I nevertheless should not receive. (This makes sense since there is no guarantee that it points to any useful memory.)

However, if a get such an invalid non-zero pointer, can I pass it to free usual way? Or is it illegal because the pointer that I get from malloc(0) may not point to the allocated allocated memory block?

Specifically, does the following code have the correct behavior:

 #include <stdio.h> #include <stdlib.h> int main() { int* x = (int*) malloc(0); if (x == NULL) { printf("Got NULL\n"); return 0; } else { printf("Got nonnull %p\n", x); } free(x); // is calling `free` here okay? } 
+43
c memory-management malloc free
Jun 02 '17 at 14:24
source share
2 answers

Standard C99 (actually WG14 / N1124. Committee draft - May 6, 2005 ISO / IEC 9899: TC2) speaks of malloc() :

The pointer returns the points to the beginning (low byte address) of the allocated space. If space cannot be allocated, the null pointer is back. If the size of the requested space is zero, the behavior is determined by the implementation: either a null pointer is returned, or the behavior is as if the size were some non-zero value, except that the returned pointer should not be used to access the object

and near free() :

Otherwise, if the argument does not match the pointer previously returned by the calloc, malloc, or realloc function, or if the space was freed by calling free or realloc, the behavior is undefined.

IEEE Std 1003.1-2008 (POSIX), 2016 release talks about free() :

The free () function must call the space pointed to by ptr to be freed; that is, available for further distribution. If ptr is a null pointer, no action will be taken. Otherwise, if the argument does not match the pointer previously returned by the function in POSIX.1-2008 that allocates memory as if it were malloc (), or if the space was freed up by calling free () or realloc (), the behavior is undefined.

So, no matter what *alloc() returns, you can go to free() .

Regarding current malloc() implementations:

FreeBSD uses the provided jemalloc, which makes

 void * je_malloc(size_t size) { void *ret; size_t usize JEMALLOC_CC_SILENCE_INIT(0); if (size == 0) size = 1; [...] 

While Apple libmalloc does

 void * szone_memalign(szone_t *szone, size_t alignment, size_t size) { if (size == 0) { size = 1; // Ensures we'll return an aligned free()-able pointer [...] 

GLIBC also changes the requested size; it uses a call to this macro with the requested size in bytes as a parameter to align the size with a certain border or just the minimum allocation size:

 #define request2size(req) \ (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \ MINSIZE : \ ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK) 
+41
Jun 02 '17 at 14:33
source share

Yes, in fact you should do this to avoid a possible memory leak.

The malloc system usually returns a hidden control unit in space immediately before the pointer with information, such as the size of the distribution. If the allocation size is zero, this block still exists and takes up memory if malloc returns a nonzero value.

+25
Jun 02 '17 at 14:28
source share



All Articles