Tuesday, September 14, 2010

Is malloc(0) call is Valid or invalid?

Yes malloc(0) is valid but this is implementation, system dependent(Memory manager/OS/GLIBC).

Take an example for 32 bit machine(Linux/Solaris):
char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
printf("Got a null pointer\n");
else
printf("Got a valid pointer\n");

I have tried the above code snippet in linux/solaris machine.Its output is:
Got a valid pointer

Even a request for zero bytes (i.e., malloc(0)) returns a pointer to something of the minimum allocatable size.

The above is implementation dependent.Therfore malloc(0) call is Valid.

few things to know for details see below *Vital statistics column:
Minimum allocated size:
4-byte ptrs: 16 bytes (including 4/8 bytes overhead)


Alignment: 2 * sizeof(size_t) (default)
(i.e., 8 byte alignment with 4byte size_t). This suffices for nearly all current machines and C compilers. However, you can define MALLOC_ALIGNMENT to be wider than this if necessary.

Malloc padded to a multiple of 8 for 8 byte alignment.Minimum overhead: 8 byte[Each malloced chunk has a hidden word of overhead holding size and status information.]

take an example and run this on linux/solaris 32 bit machine:
int j, *buf;

for (j = 0; j < 10; j++) {
buf = (int *) malloc(10);
printf("malloc(10) returned 0x%x\n", buf);
}

malloc(10) returned 0x20968
malloc(10) returned 0x20980
malloc(10) returned 0x20998
malloc(10) returned 0x209b0
malloc(10) returned 0x209c8
malloc(10) returned 0x209e0
malloc(10) returned 0x209f8
malloc(10) returned 0x20a10
malloc(10) returned 0x20a28
malloc(10) returned 0x20a40

Here malloc() allocates some extra bytes(overhead bytes that contains allocated memory size etc) each time it is called so that it can do bookkeeping. These extra bytes help out when free() is called.
These extra bytes are often allocated before the returned memory.
The difference for every 10 byte memory allocation is 24 bytes[16 byte for user(10 + 6 byte for making 8 byte alignment) + 8 byte overhead].

Overhead contains as following info and that is used during free the memory:

  • The actual size of the allocated memory block.
  • An indicator as to whether the block is in use, or has been freed.

The above information is based on GLIBC.For more information refer Glibc source code.

Please note that the smallest allowed allocation is 32 bytes on a 64-bit system. 

 ======================================================================
Below taken from GLIBC code:
* Vital statistics:

  Supported pointer representation:       4 or 8 bytes
  Supported size_t  representation:       4 or 8 bytes
       Note that size_t is allowed to be 4 bytes even if pointers are 8.
       You can adjust this by defining INTERNAL_SIZE_T

  Alignment:                              2 * sizeof(size_t) (default)
       (i.e., 8 byte alignment with 4byte size_t). This suffices for
       nearly all current machines and C compilers. However, you can
       define MALLOC_ALIGNMENT to be wider than this if necessary.

  Minimum overhead per allocated chunk:   4 or 8 bytes
       Each malloced chunk has a hidden word of overhead holding size
       and status information.

  Minimum allocated size: 4-byte ptrs:  16 bytes    (including 4 overhead)
              8-byte ptrs:  24/32 bytes (including, 4/8 overhead)

       When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte
       ptrs but 4 byte size) or 24 (for 8/8) additional bytes are
       needed; 4 (8) for a trailing size field and 8 (16) bytes for
       free list pointers. Thus, the minimum allocatable size is
       16/24/32 bytes.

       Even a request for zero bytes (i.e., malloc(0)) returns a
       pointer to something of the minimum allocatable size.

       The maximum overhead wastage (i.e., number of extra bytes
       allocated than were requested in malloc) is less than or equal
       to the minimum size, except for requests >= mmap_threshold that
       are serviced via mmap(), where the worst case wastage is 2 *
       sizeof(size_t) bytes plus the remainder from a system page (the
       minimal mmap unit); typically 4096 or 8192 bytes.

  Maximum allocated size:  4-byte size_t: 2^32 minus about two pages
               8-byte size_t: 2^64 minus about two pages

No comments: