Confusion about memory layout when allocating memory with malloc

61 views Asked by At
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
struct data {
   char name[64];
};
struct fp {
   int (*fp)();
};
void winner()
{
   printf("level passed\n");
}
void nowinner(){
   printf("level has not been passed\n");
}

int main(int argc, char **argv)
{
   struct data *d;  struct fp *f;
   d = malloc(sizeof(struct data));
   f = malloc(sizeof(struct fp));
   int* new_p = malloc(sizeof(int));
   int* new_p2 = malloc(sizeof(int));
   f->fp = nowinner;
   printf("data is at %p, fp is at %p\n", d, f);
   strcpy(d->name, argv[1]);
   f->fp();
}

Why does the address difference between the f pointer and the p pointer amount to 80 bytes, and the difference between the f pointer and the new_p pointer is 32 bytes? Similarly, the difference between two int* pointers also results in 32 bytes. This suggests that when allocating memory with malloc, an actual 80 bytes are being used, which is a significant waste of memory. Additionally, allocating an int with malloc also occupies an astonishing 32 bytes. Won't this lead to massive memory fragmentation?

my gcc

gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.

Debugging output:

I initially discovered this issue when examining the memory address of the f p pointer. There was a 16-byte gap between the f p pointers. I considered the principle of structure memory alignment, but upon further reflection, it seemed impossible because the name array occupies 64 bytes, which should align properly no matter how it's calculated. So, I tried mallocating an int and found that mallocing an int surprisingly took up 32 bytes, with a gap of 28 bytes between them? Wouldn't this result in a significant amount of memory fragmentation?

1

There are 1 answers

0
Jeff Learman On
  1. Every chunk allocated has a "hidden" header (preceding the location pointed to) that allows the system to return the memory to the available space.
  2. Additional space may be allocated to reduce fragmentation (lots of tiny available blocks, which can hinder the ability to allocate large blocks.)
  3. Additional space may be reserved to accommodate data alignment as required by the machine architecture.