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 th开发者_高级运维ere 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.
Besides the ones that you are mentioning (some are extensions):
- variables on the stack are also dynamically allocated. Recursion is a way to allocate and use that.
- C99 has variable length arrays (as BlueRaja mentions).
- On some systems you even have an
alloca
call that lets you allocate variable length chunks in the stackframe. - POSIX has mapping of memory segments and files, with combinations of
shm_open
oropen
andmmap
. - SysV IPC has
shmget
etc calls
One 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.
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.
malloc: lets say you have ptr=(int *)malloc(10); This allocates 10 contiguous bytes of memory space and the address of the first byte is stored in pointer variable ptr. The allocated memory now contains the garbage value.
So if i varies from 0 to 3 scanf("%d",ptr+i); stores 4 integers at 4 contiguous location. ptr has the address of 1st integer,ptr+1 has the address of 2nd number and so on.
Hence printf("%d",atstrick(ptr+i)); will print corresponding values.
Unlike memory allocated for variables and arrays,dynamically allocated has no name associated with it. As seen above.
calloc: It is similar to malloc except two difference: 1. Declaration: ptr=(int *)calloc(5,sizeof(int)); Here we have two arguments, 5 is no of blocks allocated and 2nd argument is equal to 4 bytes.This is equivalent to ptr=(int *)malloc(5*sizeof(int)); 2.In calloc memory intially allocated is not garbage, but it is 0. Both malloc and calloc returns NULL if there is not sufficient memory available in heap.
精彩评论