I'm aware of the following:
- malloc
- calloc
- realloc
What are the differences between these? Why does malloc seem to be used almost exclusively? Are there behavioral differences between compilers?
I'm aware of the following:
What are the differences between these? Why does malloc seem to be used almost exclusively? Are there behavioral differences between compilers?
malloc
allocates memory. The contents of the memory are left as-is (filled with whatever was there before).
calloc
allocates memory and sets its contents to all-zeros.
realloc
changes the size of an existing allocated block of memory, or copies the contents of an existing block of memory into a newly allocated block of the requested size, and then deallocates the old block.
Obviously, realloc
is a special-case situation. If you don't have an old block of memory to resize (or copy and deallocate), there's no reason to use it. The reason that malloc
is normally used instead of calloc
is because there is a run-time cost for setting the memory to all-zeros and if you're planning to immediately fill the memory with useful data (as is common), there's no point in zeroing it out first.
These functions are all standard and behave reliably across compilers.
calloc is likely just implemented as something similar to:
void * calloc(size_t nmemb, size_t size) {
size_t len = nmemb * size);
void * ptr = malloc(len);
if (ptr) {
return memset(ptr, 0, len);
}
return ptr;
}
So it just adds a multiply before and a clear after the malloc.
malloc could be (but probably isn't ever) implemented as:
void * malloc(size_t size) {
return realloc(NULL, size);
}
since you can pass realloc a NULL pointer as the previous pointer, but malloc is most likely not implemented like that because it would slow down all mallocs and because realloc probably uses malloc.
The main thing to know about realloc is that it is often capable of determining the actual size of the block of memory that any of the heap allocation routines returned and see if the block is big enough already or in some cases if it would be best try to shrink the block or move it.
void realloc(void * ptr, size_t size) {
size_t alen = MALLOC_LENGTH_OF(ptr); // this just stands for some method of determining
// the size of the block that was allocated, and could
// be looking it up in a table or looking at a place
// several bytes before the pointer, or some other
// implementation specific thing
if (0 == size) {
free(ptr);
return NULL;
}
if (alen >= size) {
return ptr; // big enough, and not worrying about it being too big
}
void new_ptr = malloc(size); // since I said that malloc most likely isn't
// implemented using realloc using malloc here is ok
if (new_ptr && ptr) {
memcpy(new_ptr, ptr, alen);
}
free(ptr);
return new_ptr;
}
Malloc is used more because it is simplest. Programmers can often make their allocations big enough to begin with that they don't have to worry about resizing them with realloc, and very often clearing the memory is not needed.
There are different behaviors among different libraries, and you can even link programs with other versions just to get this different behavior without (usually without changing the compiler).
Some malloc libraries are for debugging and error detection. Others may offer better performance. Some are optimized for allocating memory for several different threads at the same time, and avoid the different threads needing to lock down the entire heap to perform an allocation or free.
All of them should provide the same semantics from the applications perspective, though.
Besides the ones that you are mentioning (some are extensions):
alloca
call that lets you allocate variable length chunks in the stackframe.shm_open
or open
and mmap
.shmget
etc callsOne method to allocate memory that hasn't been mentioned is alloca(size_t size)
which reserves size bytes of memory on the current stack frame and automatically frees the memory again when you leave the stack frame.