Here is my program:
#include <stdio.h>
#include <stdlib.h>
main(){
char *p1, *p2, *p3, *p4;
p1 = (char*)malloc(10);
p2 = (char*)malloc(10);
p3 = (char*)malloc(16);
p4 = (char*)malloc(32);
printf("p1 points at: %d\n", p1);
printf("p2 points at: %d\n", p2);
printf("p3 points at: %d\n", p3);
printf("p4 points at: %d\n\n", p4);
system("PAUSE");
}
This produces the following output on my PC:
p1 points at: 6492080
p2 points at: 6492104
p3 points at: 6492128
p4 points at: 6492152
So, each memory space that malloc allocates starts 24 bytes further, no matter how many bytes are allocated. Why is that? I appreciate your help!
The exact behavior of malloc
is determined by your particular implentation (compiler/libc/OS). By printing out the addresses, your program is engaged in undefined behavior.
If you narrowed the scope of your question by telling us what compiler you are using, what OS you are on, what architecture, and what version of libc you are using, then we might be able to give a more specific answer about that implementation and why the number is 24.
My GUESS would be that in your implementation, each malloc
ed region of memory needs to start at an address that is a multiple of 8, and also there are 8 bytes of overhead.
EDIT: If you called malloc
again to create p5 after p4, the pattern definitely cannot continue, so your statement of "each memory space that malloc allocates starts 24 bytes further, no matter how many bytes are allocated." is false.
There is no guarantee that an int
and some void*
or char*
pointer have the same size (on my Debian/Linux/AMD64 system, int
-s are 32 bits but pointers are 64 bits). You might want to include <stdint.h>
and use intptr_t
.
The implementation of malloc
may sometimes reserve a few bytes before the allocated zone for housekeeping purposes. And malloc
shoud always return an enough aligned pointer (alignment constraints are compiler, runtime, and processor specific). There is absolutely no guarantee that malloc
returns an increasing sequence of results in time (especially in real programs, where millions of calls to malloc
are mixed with millions of calls to free
; you may even have some memory fragmentation in such long running processes).
And I am quite sure that if you add a p5 = malloc(10120);
after your p4
you won't see a 24 bytes distance between p5
and p4
, since when it is successful malloc
guarantee that its result is not an alias of any previous result, so that p5
should have at least a distance of 32 bytes with p4
(which contains a 32 bytes chunk).
Almost always, the standard C library implements malloc
above some lower-level primitive, usually some syscall to fetch consecutive virtual memory pages. On Linux, these syscalls are often mmap(2) (perhaps with sbrk(2)
) and since Linux systems are mostly free software you could actually study and improve the implementation of malloc
e.g. Musl Libc implementation of malloc (the more common GNU libc malloc
implementation is perhaps more complex to understand). So you could learn more by switching to Linux.
An implementation of malloc
could in theory always fail. In practice, malloc
may succeed, but you should always test for the failure case.
Of course, most implementations care about free
and re-use recently free
-d memory zone (without any syscalls), if possible, in their malloc
implementation. How to organize the heap to be able make malloc
and free
efficient is difficult (and may be still a research subject, if you want it to be very good).
You might want to read the wikipedia page on malloc.
malloc
shall allocate space for an object of size
size. Nothing prevents your implementation to add padding bytes for alignment purpose, for instance. Another example: some memory management implementations keep the size of your block before the allocated space.
If you want more details, you should precise your implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With