Hi All,
Many of you would have already known how memory allocation happens when
malloc() function is used in C language. This article is just the gist of my study on
malloc() function.
What happens when you invoke malloc()?
When the C compiler sees
malloc(4) function in the program, it requests the underlying OS (Operating System) to allocate 4 bytes and the OS, upon allocation, returns the
block containing the address to the next block in the memory + the starting address of the memory allocated + the size of the block (here 4 bytes), rounded off to the multiples of size of the
most restricted datatype on the machine.
Example:
int *p;
p=(int*)malloc(sizeof(int));
printf("%u\n",p);
p=(int*)malloc(sizeof(int));
printf("%u\n",p);
p=(int*)malloc(sizeof(int));
printf("%u\n",p);
p=(int*)malloc(sizeof(int));
printf("%u\n",p);
returns...
152002568
152002584
152002600
152002616
These are separated by 16 bytes, on my 32-bit machine! Please find the math for this below.
I will try to illustrate it with another bigger example there and put math of both examples together.
What is the most restrictive datatype?
For each machine, there is a most restrictive type. It is not unique and varies on different machines. It means that if you can store the most restricted datatype in an address, you can store any primitive type. Generally it will be
double (as it is on my machine) but I read somewhere that it can be
int or
float too.
Yet another example, with calculations?
Consider creating the following structure and allocate memory using
malloc() function.
struct test
{
char c;
char f;
int a;
int b;
float d;
double e;
double g;
double h;
double i;
};
int main()
{
struct test *t;
t=(struct test*)malloc(sizeof(struct test));
printf("%d\n",sizeof(struct test));
printf("%u\n",t);
t=(struct test*)malloc(sizeof(struct test));
printf("%u\n",t);
t=(struct test*)malloc(sizeof(struct test));
printf("%u\n",t);
t=(struct test*)malloc(sizeof(struct test));
printf("%u\n",t);
t=(struct test*)malloc(sizeof(struct test));
printf("%u\n",t);
t=(struct test*)malloc(sizeof(struct test));
printf("%u\n",t);
return 0;
}
returns...
48
140615688
140615744
140615800
140615856
140615912
140615968
Reason goes here...
On a 32-bit machine,
char occupies 1 byte,
int and
float, 4 bytes while
double occupies 8 bytes. So the structure essentially needs 46 bytes
but 48 bytes are allocated because it
should be in the multiples of (8 bytes - most restricted datatype,
double on a 32-bit machine).
Now, on a 32-bit machine, each
word is addressed by 32 bits (==4 bytes). So, as per the explanation given above w.r.t. block returned by
malloc(), it has to return the address to next block (4 bytes) + address of allocated block (4 bytes) + size of structure (48 bytes), i.e.
56 bytes. This is the reason why we got addresses separated by 56 bytes for each allocation!
Similar math follows for the first example I quoted...
On a 32-bit machine,
int occupies 4 bytes, but address to the next block (4 bytes) and address of the currently allocated block (4 bytes) add up to it making it 12 bytes. But the actual memory allocated must be in the multiples of most restricted datatype on the underlying machine which is
double ( 8 bytes) and hence 16 bytes are allocated.
Hope this information will be useful to you all. I would like to have your comments/feedback on this. I am open for discussion on this topic! :)