An alternative way to get an estimate of the stack usage is to read the stack pointer value in every function and update the minimum and maximum stack pointer variables. At the end of the program the difference between the two values will give you the estimate.
In order to read the value of the stack pointer you can:
- Implement an assembly function (doing
mov r/eax, r/esp
+ ret
for the x86 CPU)
- Do the same (w/o ret, of course) using inline assembly if supported by your compiler
- Implement something like the below (which may not work always/everywhere due to code optimization)
Code:
#include <stdint.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
// uintptr_t is an unsigned integer type from stdint.h
// that is capable of holding a pointer.
// If you don't have it in your compiler, use an
// equivalent, which may be size_t (stddef.h) or
// UINT_PTR (windows.h) or something else.
uintptr_t StackPointerMin = (uintptr_t)-1;
uintptr_t StackPointerMax = 0;
void UpdateStackUsageInner(int dummy, ...)
{
va_list ap;
volatile char* p;
uintptr_t StackPointer;
va_start(ap, dummy);
p = va_arg(ap, volatile char*);
StackPointer = (uintptr_t)p;
if (StackPointer < StackPointerMin) StackPointerMin = StackPointer;
if (StackPointer > StackPointerMax) StackPointerMax = StackPointer;
va_end(ap);
}
void UpdateStackUsage()
{
volatile char c = 'a';
UpdateStackUsageInner(0, &c);
}
void DoSomething(void)
{
char c[1024+1];
UpdateStackUsage();
memset(c, '*', sizeof(c));
c[sizeof(c)-1] = '\0';
printf("%s\n", c);
}
int main(void)
{
UpdateStackUsage();
DoSomething();
printf("Approximate stack usage: %lu\n",
(unsigned long)(StackPointerMax - StackPointerMin));
return 0;
}
Output:
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
****************************************************************
Approximate stack usage: 1040
I also know that some compilers support hooking function entry (and probably exit), which can simplify the task because with that you won't need to insert UpdateStackUsage();
into all/many of your functions. That's been discussed here.