Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C embedded systems stack and heap size

How could I determine the current stack and heap size of a running C program on an embedded system? Also, how could I discover the maximum stack and heap sizes that my embedded system will allow? I thought about linearly calling malloc() with an increasing size until it fails to find the heap size, however I am more interested in the size of the stack.

I am using an mbed NXP LPC1768, and I am using an offline compiler developed on GitHub called gcc4mbed.

Any better ideas? All help is greatly appreciated!

like image 774
CodeKingPlusPlus Avatar asked Dec 03 '22 02:12

CodeKingPlusPlus


2 Answers

For this look at your linker script, this will define how much space you have allocated to each.

For stack size usage do this:

At startup (before C main()) during initialization of memory, init all your stack bytes to known values such as 0xAA, or 0xCD. Run your program, at any point you can stop and see how many magic values you have left. If you don't see any magic values then you have overflowed your stack and weirdness may start to happen.

At runtime you can also check the last 4 bytes or so (maybe last two words, this is really up to you). If they don't match your magic value then force a reset. This only works if your system is well behaved on reset and it is best if it starts up quick and isn't doing something "real time" or mission critical.

Here's a really helpful whitepaper from IAR on the subject.

like image 170
Josh Petitt Avatar answered Dec 24 '22 23:12

Josh Petitt


A crude way of measuring at runtime the current stack size is to declare

 static void* mainsp;

then start your main with e.g:

 int main(int argc, char**argv) {
    int here;
    mainsp = (void*) &here;

then inside some leaf routine, when the call stack is deep enough, do something similar to

    int local;
    printf ("stack size = %ld\n", 
            (long) ((intptr_t) &local - (intptr_t) mainsp));

Statically estimating from full source code of an application the required stack size is in general undecidable (think of recursion, function pointers), and in practice very difficult (even on a severely restricted class of applications). Look into Couverture. You might also consider customizing a recent GCC compiler with your plugin (perhaps Bismon in mid 2021; email me to [email protected] about it) for such purposes, but that won't be easy and will give you over-approximations.

If compiling with GCC, you might use the return address bultins to query the stack frame pointer at run time. On some architectures it is not available with some optimization flags. You could also use the -Wstack-usage=byte-size and/or -Wframe-larger-than=byte-size warning options to recent GCC.

As to how heap and stack spaces are distributed, this is system dependent. You might parse /proc/self/maps file on Linux. See proc(5). You could limit stack space on Linux in user-space using setrlimit(2).

Be however aware of Rice's theorem.

With multi-threaded applications things could be more difficult. Read some Pthread tutorial.

Notice that in simple cases, GCC may be capable of tail-call optimizations. You could compile your foo.c with gcc -Os -fverbose-asm -S foo.c and look inside the generated foo.s assembler code.

If you don't care about portability, consider also using the extended asm features of GCC.

like image 25
Basile Starynkevitch Avatar answered Dec 24 '22 21:12

Basile Starynkevitch