2
\$\begingroup\$

I was testing the code below on my STM32 board, but I could't understand how the array was being allocated in the stack.

I'm assuming that there are 200 bytes of memory in STM32.

Here is the code:

void test1()
{
  char data[1000]={0};
}

void test2()
{
  char data[1000];
  data[999] = 50;
  lcdAdjustBacklight(data[999]);//just adjust back light
}

So, when I add test1() into my main() function, the program will crash when run on the MCU. Obviously, the stack is overflow. However, when I add test2() into main(), the MCU processes the program just fine. I wonder how the stack allocation works for an uninitialized array.


Edit: I finally figured it out. I checked the assembly code, in test1 the compiler allocated the memory, indeed. But in test2, the compiler optimized the array, so it does not allocated memory for it.

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Note that 'MCU will stop running' versus 'MCU still running' is not a good criterium for 'everything is OK'.

On ARM chips. the stack grows down (starts high, each nested stack frame occupies lower addresses), in most cases starting from the highest RAM address. When the stack grows too large for the available stack space, it will overwrite the heap, and after that global data. Whether this is harmful for the program depends. On what? That's mighty complex to figure out.

Note that the 'data[999]' in your 'char data[1000]' is the highest address within this variable, so it is the least likely to cause a problem. using data[0] (which is at the lowest address) is more likely to cause a problem.

Again on ARM, a function that does not call deeper functions might not use the stack at all (the return address is saved in a register, not on the stack).

So in all probability, both your programs are bad, but whether in practice that translates to 'seems to work' or 'seems to stop' is very difficult to predict.

\$\endgroup\$
3
  • \$\begingroup\$ I guess on his initialized example it's just more apparent because it's actually overwriting 1000 bytes not just 1. \$\endgroup\$
    – PeterJ
    Dec 23, 2013 at 7:50
  • \$\begingroup\$ The "test1()" will cause the "HardFault".On "test2",if there's no memory for allocation why it dose not hit the "HardFault".It seems like it doesn't allocated memory for uninitialized array member. \$\endgroup\$
    – John G
    Dec 23, 2013 at 7:53
  • \$\begingroup\$ @John: see update. \$\endgroup\$ Dec 23, 2013 at 8:53
0
\$\begingroup\$

Stack allocation for uninitialized arrays is somewhat compiler dependent. Compilers typically only adjust the stack pointer at function entry by the number of bytes the function will need. If the stack pointer is in a general register, the fact that it underflows will probably not cause an exception (but attempting to use it to write to non-existent memory probably will). But if the stack pointer register is dedicated (in hardware) then it might not be allowed to underflow.

In your test2() example, a smart compiler could notice that only one of the 1000 chars "allocated" by the programmer is needed, optimize out the generation of the array, and instead just push "50" (one or two bytes) onto the stack for the lcdAdjustBacklight() call.

Arguably, the array in test1() should have been optimized out as well, but as you've seen, it was allocated despite its not being used.

\$\endgroup\$
2
  • \$\begingroup\$ It's also possible that the compiler is allocating the 1000 bytes on the stack, but since there's no initialization, only one of them gets overwritten and it didn't happen to clobber anything in the heap that caused an immediately obvious failure. \$\endgroup\$
    – The Photon
    Dec 23, 2013 at 17:56
  • \$\begingroup\$ Indeed. Element 999 is near the end of the array closest to the most recently used stack memory, so it would be as if you'd allocated a single initialized char. This would also depend on the stack pointer not causing an exception, as in my first paragraph. \$\endgroup\$
    – JRobert
    Dec 23, 2013 at 18:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.