Peter Burden's Using of Memory Allocation Functions page is a good introduction to the use of dynamically allocated memory in C.
Most modern Unixes have memory allocation systems that perform pretty well for ordinary applications. Some cleverness in coding can give you performance improvements though. As a simple example, instead of doing:
thing= (struct whatever *)malloc(sizeof(struct whatever)); thing->buf= (char *)malloc(100); : /* process, process, process */ : free(thing->buf); free(thing);you might do
thing= (struct whatever *)malloc(sizeof(struct whatever) + 100); thing->buf= (char *)(thing+1) : /* process, process, process */ : free(thing);If we are allocating and freeing two hunks of memory together, why not just allocate one bigger hunk? It should be faster, and less memory should be wasted in rounding up hunk sizes (as many implementations do). This basic idea can be extended to routines that read in whole linked lists. The cost, of course, is that the code become more obscure and more brittle. For example, if you later decide you'd like to do a realloc() to increase the size of thing->buf, you'll have to do it in a non-obvioius way. I suspect that in most applications, this kind of thing is not worth doing.
Some versions of Unix include more than one library of memory management functions. In Solaris 2, for example, if you link with "-lbsdmalloc" you get a library that is faster (but less space efficient) than the default one, and if you link with "-lmalloc" you get one that is slower, but more space efficient. All include the standard malloc(), free(), and realloc() entry points. Similar SGI has a "-lmalloc" option that is faster than it's default. It may also be possible to find third party memory management libraries that will fit the performance needs of your application better.
#include <stdlib.h>On systems that don't have stdlib.h you might try including malloc.h or alloc.h instead. However, I usually just fall back to declaring things directly:
#ifdef HAVE_STDLIB_H # include <stdlib.h> #else char *malloc(), *realloc(); #endifHere we declare as a char * instead of as a void * because many systems old enough not to have stdlib also don't have void.
However, alloca() should not be used in portable code. Though it exists on most machines, it is not in the standards and is apparantly difficult to implement on architectures without a conventional stack. It is often buggy.
You may need the special header file alloca.h since stdlib.h often doesn't define this non-standard call.
The type of the parameter for sbrk() varies widely. Possible types include int, ptrdiff_t and intptr_t.
Note that it sets all bits to zero, which means that technically the values are not necessarily valid null pointer values. However, machines where null pointers are something other than all-zero-bits are exceedingly rare if not completely imaginary.
Modern implementations always return a void * pointer, but older ones often returned a char *. The return values from calloc(), malloc() and realloc() should always be explicitly type cast to the appropriate pointer type, like buf= (char *)calloc(20).
Memalign() comes from BSD Unix and exists on some BSD derivatives like SunOS. It is not in the standards. It is not portable.
On most modern systems, malloc() returns addresses which are multiples of 8 (or 16 on 64-bit systems), which mostly eliminates the need for memalign().
On some systems, memory allocated with memalign() cannot be released with free() or in any other way, short of exit().
malloc(0) may either return NULL or a pointer to a size zero hunk of memory.
Note that on machines with 16 bit ints, you may not be able to allocate chunks of memory bigger than MAX_INT.
This was introduced in POSIX 1003.1.d, but doesn't seem to be around everywhere.
The ANSI standard says calling realloc(NULL,size) is equivalent to malloc(size) and realloc(ptr,0) is equivalent to free(ptr), but not all pre-ANSI libraries support this.
Some systems allow pointers to freed blocks to be passed to realloc, so long as there have been no memory allocation calls (eg malloc() or calloc()) since the block was freed. This is non-portable.
Not portable. On systems that don't have it, it is reasonable to just use malloc() instead. Originated in 3.0 BSD and declared obsolete in 4.3 BSD. Not included in ANSI or POSIX standards.
In some systems, memory allocated by valloc() can not be passed to realloc() or free().