I tried to create large amount of memory in stack (int a[1000000000]
). It compiled successfully. However at run time it Segfaulted. Its perfectly agreeable that the program segfaults. My question is, why cant the compiler detect this before hand and throw an compilation error? Why should we wait till the program runs?
Also, when i allocate int a[100]
, the asm code looks like following.
00000000004004b4 <main>:
4004b4: 55 push %rbp
4004b5: 48 89 e5 mov %rsp,%rbp
4004b8: 48 81 ec 18 01 00 00 sub $0x118,%rsp (memory created for 100 bytes)
If i create for a large memory int a[1000000000]
, the asm code looks different.
00000000004004b4 <main>:
4004b4: 55 push %rbp
4004b5: 48 89 e5 mov %rsp,%rbp
4004b8: 49 bb 78 00 17 be 33 movabs $0xfffe9433be170078,%r11
4004bf: 94 fe ff
4004c2: 4c 01 dc add %r11,%rsp
Can someone please explain this? i.e Why is not the compiler taking care of this?
Compiler is not responsible for stack allocation. The stack space for the binary is reserved by the linker. For example, ld
has --stack
option:
--stack reserve
--stack reserve,commit
Specify the number of bytes of memory to reserve (and optionally commit) to be used as stack for this program. The default is 2Mb reserved, 4K committed. [This option is specific to the i386 PE targeted port of the linker]
Additionally, the process may clone itself to create other processes/threads. At that point, whoever creates a clone controls how much memory to allocate for the stack and neither compiler not linker can help there.
And, finally, operating system may have other limitations on top of it. For example, Linux has soft and hard limit for stack size and won't allow any process to create its stack if it violates the limit set for the process. See ulimit.
In theory, it is possible for a compiler to analyze the program and try to estimate total stack usage and, say, hint the linker about how much it should try to reserve for a stack. However, this becomes very problematic if, for example, dynamic linking is used. Or, for instance, program has a recursion which depth depends on a run-time variable (i.e. some graph search algorithm). Then there is no way to do that. Given that implementing such a heuristic in a compiler is far from trivial, and the fact that most programs have some sort of recursion or dynamic linking, it is simply not worth the effort.