0

I have the following code

void foo()
{   
        char *a, *b; 
        int *c, *d; 
        a = (char*)malloc(1);
        b = (char*)malloc(1);
        c = (int*)malloc(4);
        d = (int*)malloc(4);
        *a = 10; 
        *b = 20; 
        *c = 30; 
        *d = 40; 
}   

Here is the gdb output:

13      a = (char*)malloc(1);
(gdb) n
14      b = (char*)malloc(1);
(gdb) n
15      c = (int*)malloc(4);
(gdb) n
16      d = (int*)malloc(4);
(gdb) n
17      *a = 10;
(gdb) n
18      *b = 20;
(gdb) n
19      *c = 30;
(gdb) n
20      *d = 40;
(gdb) n
21  }
(gdb) p a
$1 = 0x804b008 "\n"
(gdb) p b
$2 = 0x804b018 "\024"
(gdb) x/40b a
0x804b008:  10  0   0   0   0   0   0   0
0x804b010:  0   0   0   0   17  0   0   0
0x804b018:  20  0   0   0   0   0   0   0
0x804b020:  0   0   0   0   17  0   0   0
0x804b028:  30  0   0   0   0   0   0   0
(gdb) 

Though a and b are both char pointers. Why is pointer to b equal to a + 16? Any reason for offsetting 16 bytes?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Parth Shah
  • 573
  • 1
  • 6
  • 17
  • 6
    It's needed because each allocation has to be aligned sufficiently well for any use. Also, there is often control information adjacent to the pointer that you're given, that describes the data segment that is passed. Finally, note that this is controlled by the C library implementation of `malloc()` rather than by the C compiler per se. The two are closely related, of course. – Jonathan Leffler Oct 12 '14 at 06:58
  • 3
    You should not cast the return value of `malloc()`. See http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – pmg Oct 12 '14 at 08:30
  • @Parth Shah What is the sizeof(int*) on your system? – 2501 Oct 12 '14 at 10:53

2 Answers2

4

Malloc is required to return memory that is sufficiently aligned for any fundamental type1.

In you case the alignment seem to be on 16-byte boundaries. This should satisfy alignment requirements of any fundamental type.


1 (Quoted from: ISO/IEC 9899:201x 7.22.3 Memory management functions 1)
The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated).

2501
  • 25,460
  • 4
  • 47
  • 87
1

The first 20 minutes of this video explains the reason very well in detail.

As far as I know, every memory allocation process leaves a trace in the memory which include some additional info (like, the length of the memory allocated, the next available space for the coming allocation, etc). So, let's say, if you allocate a length of 10 integers (10 * 4 bytes = 40 bytes), depending on the systems structure (whether it's 32 bits or 64 bits), the system always allocates at least +1 (maybe more for some systems) extra pointer size bytes, which points to the next free space to be allocated. That is, your malloc for 40 bytes, allocates (at least) 44 bytes on a 32 bit system.

To be more specific; if your allocation for malloc (40) returns an address of 1200, then this means:

(1) your array will be laid between the addresses 1200 & 1240,

(2) and the length of the array (or the pointer that points to the next available space) is written in the (1200 - 4) = 1196th address.

(3) so, the total allocated space for this malloc becomes 44 bytes.

Again, the trace length for the malloc info may be 4 bytes for 32 bit system, and 8 bytes for a 64 bit system. On some systems, depending on the information written, it may be even longer; but for sure, it's going to be a factor of 4 (on 32 bits), and 8 (for 64 bits).

ssd
  • 2,340
  • 5
  • 19
  • 37