1
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int a = 4;
    int *p = malloc(sizeof(int) * a);
    int *g = malloc(sizeof(int) * a);
    p += 8;
    printf("%p\n", p);
    printf("%p\n", g);
    
}

I have run this program several times, and every time the values of p and g printed at the end are the same. I'm not quite sure why this is happening - couldn't malloc theoretically pick anywhere in memory to have p and g point to? Why does p + 8 always equal g? Any clarification would be much appreciated.

Thanks!

  • 1
    You go to a bakery and ask for a donut. The clerk gets it for you. You ask for another. The clerk gets one that was next to the first one. You do this every day, and, every day, the clerk gives you two donuts that were next to each other. Even on days when there are more or fewer donuts on the shelf, the clerk gets the next two for you. Why are you surprised? – Eric Postpischil Apr 13 '22 at 23:14
  • On modern systems with [virtual memory](https://en.wikipedia.org/wiki/Virtual_memory), every time you run the program, it starts with the exact same (virtual) memory setup, so there's no reason why `malloc` can't behave exactly the same way. On the other hand, `malloc` might deliberately behave differently for security reasons, e.g. [ASLR](https://en.wikipedia.org/wiki/Address_space_layout_randomization). – user3386109 Apr 13 '22 at 23:14
  • @EricPostpischil That seems like a poor analogy, since he's probably thinking "Every day I go to the bakery, and the donuts are in different positions because other people have come and gone before me – Barmar Apr 13 '22 at 23:27
  • Actually, Barmar, this is equivalent to him always being the very first customer each day :) – 500 - Internal Server Error Apr 13 '22 at 23:34
  • Let's say p is given the value of 0x1000. Then, this is &p[0]. Likewise, &p[1] = 0x1004, &p[2] = 0x1008, &p[3] = 0x100c. Overall, the array p covers memory addresses 0x1000 to 0x100f. But, isn't p + 8 equal to &p[8]? What happens to the memory where p[4 to 7] would normally be stored? – Edric Antoine Apr 13 '22 at 23:36
  • What is the value of `sizeof(int)` and `sizeof(int*)`? – Schwern Apr 13 '22 at 23:40
  • Sizeof(int) is 4, I know. And sizeof(int*) is 8 here. So, p + 8 = p + (8 * sizeof(int)) = p + 32 bytes. But, if g is the immediate next memory address, shouldn't it be p + 4 = p + 16 bytes ? Since the array p only takes up addresses p + 0 .... p + 15. – Edric Antoine Apr 13 '22 at 23:45
  • @Barmar in fact he is always the first customer of the day in this case, each run of this app creates a brand new donut store – pm100 Apr 14 '22 at 00:05
  • @EdricAntoine Some `malloc` implementations store bookkeeping information in the bytes *before* the returned pointer. That information may be used by `free` when releasing the memory. For example, if `malloc` returns 0x1000, then there may be 16 bytes of bookkeeping information starting at address 0x0ff0. On the other hand, `malloc` may just be enforcing a minimum allocation size of 32 bytes. – user3386109 Apr 14 '22 at 00:06
  • Does this answer your question? [Why does malloc allocate a different number of bytes than requested?](https://stackoverflow.com/questions/430163/why-does-malloc-allocate-a-different-number-of-bytes-than-requested) – Oka Apr 14 '22 at 00:08
  • ...or [this](https://stackoverflow.com/q/6389120/2505965), or maybe [this](https://stackoverflow.com/q/13064850/2505965), or even [this!](https://stackoverflow.com/q/1518711/2505965) – Oka Apr 14 '22 at 00:11

1 Answers1

2

I have run this program several times, and every time the values of p and g printed at the end are the same

This is because of how your memory happened to be allocated.

The first malloc allocates memory for 4 integers. Let's say they're 4 bytes each so 16 bytes.

0              1              2              3 
0123456789abdef0123456789abdef0123456789abdef0123456789abdef
^--------------
p

The second malloc allocates memory for another 4 integers. This memory could be allocated in any free slot, but it just so happens to be like so.

0              1              2              3 
0123456789abdef0123456789abdef0123456789abdef0123456789abdef
^--------------               ^--------------
p                             g

If you add 8 to p, that moves it by the size of 8 integers, 32 bytes, which is g.

What's in the memory in the gap? Who knows. Memory can be allocated however malloc thinks appropriate.


However, there is no guarantee the memory will be allocated this way. On my system p += 4 works meaning there's no gap.

Schwern
  • 153,029
  • 25
  • 195
  • 336