You learn fairly early on that the call stack is small and everything on it must have its size known ahead of time by the compiler. Anything large and/or dynamically-sized goes on the heap. This is just the way it is.
But I was thinking about it: it's all just memory; why can't the stack expand to fit the data (assuming that data doesn't need to be returned outside of the current stack frame)? And perhaps even more strange, why can't more memory be requested for dynamically-sized values as needed? Why does everything on the stack need to have a statically-known size?
And then I found this C function that seems to do just this (but is very rarely used): https://linux.die.net/man/3/alloca
The best explanation I could gather from reading different discussions on the internet is:
1) You don't put large amounts of data on the stack because the stack is small
2) The stack is small because memory address space in 32-bit systems was really limited so you didn't want to eat it up reserving stack space for each thread
3) Stack frame sizes are known at compile time because... that's the way C did it? Maybe it allows for some compiler optimizations? Or something?
Am I missing something, or is this a vestigial idea? Wouldn't cache usage be way better if large/dynamic data structures could go on the stack? Has anyone explored this?
Take Linux, a giant user of C language, as an example. Allocating a large chuck of memory on stack is just not useful, even given unlimited amount of memory. You note the most critical reason yourself in the post: (assuming that data doesn't need to be returned outside of the current stack frame) However, large data structures are almost always for others to use. Just consider sys_clone (that the kernel eventually generates a body for the new thread) or sys_mmap (that the kernel manipulates existing virtual memory area structures from elsewhere). Allocating them on the stack seems pointless.