stack size issue


First of all, compiler version:

clang -v
Apple clang version 3.1 (tags/Apple/clang-318.0.45) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin11.3.0
Thread model: posix

I am migrating an old C++ library to use clang, and it has some a stack size checking code, the essential part is like below:

unsigned char* init_stack_base; //this is set before calling recurse()

void recurse() {
unsigned char buf[0x100];
unsigned long long bytes_used;
bytes_used = (init_stack_base - buf);
if (bytes_used > STACK_LIMIT + 0x100)
my_assert(); // void my_assert();

The variable size for one recurse() call is sizeof(buf) + sizeof(bytes_used). which is 256+8= 264, of course I need consider the stack is aligned with 16bytes, so it will be 0x110 (272). This is exactly the number I got from LLVM GCC 4.2.

The interesting thing is, when I switch to clang, it reserves 0x120 bytes for variables. As a result, the code now asserts because the STACK_LIMIT is defined with the assumption above.

Anyone can explain why clang needs alloc extra 16 bytes stack for the same code?

If you need test it, I pasted the test program at:


my_assert is inlined and it uses the additional stack space for the


Hi Joerg,

Thanks for the reply. I re-tried with -O0 so the my_assert function isn't inlined and the stack alloc is still 0x120.

Here's how I get the result.

clang -g -O0 -lstdc++ test_stack_alloc.cpp -o test_stack_alloc
otool -t -V test_stack_alloc | c++filt

0000000100000cb0 pushq %rbp
0000000100000cb1 movq %rsp,%rbp
0000000100000cb4 subq $0x00000120,%rsp
0000000100000cbb movq 0x00000386(%rip),%rax
0000000100000cc2 movq (%rax),%rax
0000000100000cc5 movq %rax,0xf8(%rbp)
0000000100000cc9 callq check_stack_limit()
0000000100000cce leaq 0xfffffef0(%rbp),%rax
0000000100000cd5 movq 0x000003e4(%rip),%rcx
0000000100000cdc subq %rax,%rcx
0000000100000cdf movq %rcx,0xfffffee8(%rbp)
0000000100000ce6 cmpq $0x0001e100,0xfffffee8(%rbp)
0000000100000cf1 jbe 0x100000cfc
0000000100000cf7 callq my_assert()
0000000100000cfc callq recurse()
0000000100000d01 callq recurse()
0000000100000d06 movq 0x0000033b(%rip),%rax
0000000100000d0d movq (%rax),%rax
0000000100000d10 movq 0xf8(%rbp),%rcx
0000000100000d14 cmpq %rcx,%rax
0000000100000d17 jne 0x100000d26
0000000100000d1d addq $0x00000120,%rsp
0000000100000d24 popq %rbp
0000000100000d25 ret
0000000100000d26 callq 0x100000d94 ; symbol stub for: ___stack_chk_fail
0000000100000d2b nopl 0x00(%rax,%rax)

Here's the LLVM GCC 4.2 .1 generates.

0000000100000bc0 pushq %rbp
0000000100000bc1 movq %rsp,%rbp
0000000100000bc4 subq $0x00000110,%rsp
0000000100000bcb movq 0x0000047e(%rip),%rax
0000000100000bd2 movq (%rax),%rax
0000000100000bd5 movq %rax,0xf8(%rbp)
0000000100000bd9 callq check_stack_limit()
0000000100000bde movq 0x000004f3(%rip),%rax
0000000100000be5 leaq 0xfffffef8(%rbp),%rcx
0000000100000bec subq %rcx,%rax
0000000100000bef movq %rax,0xfffffef0(%rbp)
0000000100000bf6 movq 0xfffffef0(%rbp),%rax
0000000100000bfd cmpq $0x0001e100,%eax
0000000100000c03 jbe 0x100000c0a
0000000100000c05 callq my_assert()
0000000100000c0a callq recurse()
0000000100000c0f callq recurse()
0000000100000c14 movq 0x00000435(%rip),%rax
0000000100000c1b movq (%rax),%rax
0000000100000c1e movq 0xf8(%rbp),%rcx
0000000100000c22 cmpq %rcx,%rax
0000000100000c25 jne 0x100000c30
0000000100000c27 addq $0x00000110,%rsp
0000000100000c2e popq %rbp
0000000100000c2f ret
0000000100000c30 callq 0x100000d46 ; symbol stub for: ___stack_chk_fail
0000000100000c35 nopl 0x00(%rax,%rax)
0000000100000c3a nopw 0x00(%rax,%rax)