Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory allocation with malloc in C

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!

like image 813
mgus Avatar asked Oct 20 '12 15:10

mgus


3 Answers

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 malloced 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.

like image 191
David Grayson Avatar answered Sep 28 '22 01:09

David Grayson


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.

like image 27
Basile Starynkevitch Avatar answered Sep 28 '22 02:09

Basile Starynkevitch


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.

like image 27
md5 Avatar answered Sep 28 '22 01:09

md5