There are really three types of SRAM memory:
- Static variables - allocated at the low part of RAM
- The stack - allocated at top of RAM and growing downwards
- The heap - allocated after static variables and growing upwards
Are all the local variables from the calling method also pushed onto the stack as well? They must-- I don't see how we'd keep track of local variables otherwise.
Not exactly. Local variables are indeed on the stack, but the stack pointer is adjusted to allow for them (they are not literally pushed or popped).
Judging by a disassembly of some test code, entering a function with a substantial amount of local variables (ie. more than can fit into registers), the compiler generates code to subtract x from the stack pointer (where x is the number of bytes in local variables). At the end of the function the compiler adds x back to the stack pointer. Thus the stack area also stores local variables.
If you are not recursing, there wouldn't be a heap of difference between using static variables, and auto variables. The memory has to come from somewhere.
Without seeing your code it is hard to say more, but if your functions allocate a lot of memory for local variables, there will be trouble brewing. eg.
void foo ()
{
char bar [200];
...
}
Each time foo is called you will use up 202 bytes of stack (200 for "bar", plus the return address).
Actually judging by the disassembly, it will be more than 2 bytes for the function call. For example it seems to save registers 28 and 29, which is another 2 bytes.
b6: df 93 push r29
b8: cf 93 push r28
...
e2: cf 91 pop r28
e4: df 91 pop r29
e6: 08 95 ret
Is there a way I can program this to avoid having such a large stack?
Don't use auto variables? If you are only nested 7 deep or so, the function calls themselves aren't the problem.
Why isn't there some sort of protection to prevent the heap and stack from overlapping? Don't they protect against this on other processors?
I don't see how the processor can easily do this. When you malloc something it could conceivably make sure it doesn't go past the bottom of the stack, but when you do a function call, how will the processor know where the top of the heap is? The heap is purely a piece of code in a library. It isn't inherent in the processor architecture.
And even if the processor could somehow detect that calling a function would overwrite the heap, what would it do exactly? Stop? Well the code effectively does that anyway if the stack and heap collide.