C Memory Management – Understanding Stack Allocation and Alignment

c++memory-alignmentmemory-managementstack

I'm trying to understand how stack alignment works as described in what is "stack alignment"? but I have trouble getting a small example to demonstrate the said behaviour. I'm examining the stack allocation of my function foo:

void foo() {
    int a = 0;
    char b[16];
    b[0] = 'a';
}

I compiled the source file with gcc -ggdb example.c -o example.out (i.e without any compiler flags) and the assembler dump from gdb reads:

(gdb) disassemble foo
Dump of assembler code for function foo:
0x08048394 <+0>:    push   %ebp
0x08048395 <+1>:    mov    %esp,%ebp
0x08048397 <+3>:    sub    $0x20,%esp
0x0804839a <+6>:    movl   $0x0,-0x4(%ebp)
0x080483a1 <+13>:   movb   $0x61,-0x14(%ebp)
0x080483a5 <+17>:   leave  
0x080483a6 <+18>:   ret    
End of assembler dump.

My stack is allocated in chunks of 16 bytes (I verified this with several other tests). According to the assembler dump here 32 bytes have been allocated because (16 < 4+16 < 32), however I expected integer 'a' to be allocated on the first 16 bytes and then the character array to be allocated on the next 16 bytes (leaving a space of 12 bytes in-between). But it seems both the integer and the character array have been allocated a contiguous chunk of 20 bytes, which is inefficient as per the discussion i referred above. Can someone please explain what I'm missing here?

EDIT: I came to the conclusion that my stack is allocated in chunks of 16 bytes with a program like below:

void foo() {
    char a[1];
}

And the corresponding assembler dump:

(gdb) disassemble foo
Dump of assembler code for function foo:
0x08048394 <+0>:    push   %ebp
0x08048395 <+1>:    mov    %esp,%ebp
0x08048397 <+3>:    sub    $0x10,%esp
0x0804839a <+6>:    leave  
0x0804839b <+7>:    ret    
End of assembler dump.

You can see that 16 bytes have been allocated on the stack for a character array of size 1 (only 1 byte needed). i can increase the size of the array up to 16 and the assembler dump stays the same, but when it is 17, it allocates 32 bytes on the stack. I have run many such samples and the result is the same; stack memory is allocated in chunks of 16 bytes. A similar topic has been discussed in Stack allocation, padding, and alignment but what I'm more keen on finding out is why alignment has no effect in my example.

Best Answer

I think you're missing the fact that there is no requirement for all stack variables to be individually aligned to 16-byte boundaries.

Related Question