Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to measure a functions stack usage in C?

Tags:

c

stack-memory

Is there a way I can measure how much stack memory a function uses?

This question isn't specific to recursive functions; however I was interested to know how much stack memory a function called recursively would take.

I was interested to optimize the function for stack memory usage; however, without knowing what optimizations the compiler is already making, it's just guess-work if this is making real improvements or not.

To be clear, this is not a question about how to optimize for better stack usage

So is there some reliable way to find out how much stack memory a function uses in C?


Note: Assuming it's not using alloca or variable-length arrays, it should be possible to find this at compile time.

like image 1000
ideasman42 Avatar asked Feb 12 '15 21:02

ideasman42


People also ask

How do I check my stack usage?

The most common way to determine the deepest stack usage is to initialize the stack memory with some known but unusual value, then periodically (or at the end of a big test run) see where that pattern stops. This is exactly how the IAR IDE determines the amount of stack used.

How do you measure stack size?

size() method in Java is used to get the size of the Stack or the number of elements present in the Stack. Parameters: The method does not take any parameter. Return Value: The method returns the size or the number of elements present in the Stack.

How does functions affect the stack consumption?

Each called function may increase the amount of data on the stack. Those functions that are called may call other functions, and so on. This again, depends on the snapshot in time of the execution. However, one can produce an approximate maximum increase of the stack by the other called functions.

How big is the stack of a program?

Stacks are temporary memory address spaces used to hold arguments and automatic variables during invocation of a subprogram or function reference. In general, the default main stack size is 8 megabytes.


3 Answers

Using warnings

This is GCC specific (tested with gcc 4.9):

Add this above the function:

#pragma GCC diagnostic error "-Wframe-larger-than="

Which reports errors such as:

error: the frame size of 272 bytes is larger than 1 bytes [-Werror=frame-larger-than=]

While a slightly odd way method, you can at least do this quickly while editing the file.

Using CFLAGS

You can add -fstack-usage to your CFLAGS, which then writes out text files along side the object files. See: https://gcc.gnu.org/onlinedocs/gnat_ugn/Static-Stack-Usage-Analysis.html While this works very well, its may be a little inconvenient depending on your buildsystem/configuration - to build a single file with a different CFLAG, though this can of course be automated. – (thanks to @nos's comment)


Note,

It seems most/all of the compiler natural methods rely on guessing - which isn't 100% sure to remain accurate after optimizations, so this at least gives a definitive answer using a free compiler.

like image 100
ideasman42 Avatar answered Sep 28 '22 00:09

ideasman42


You can very easily find out how much stack space is taken by a call to a function which has just one word of local variables in the following way:

static byte* p1;
static byte* p2;
void f1()
{
    byte b;
    p1 = &b;
    f2();
}
void f2()
{
    byte b;
    p2 = &b;
}
void calculate()
{
    f1();
    int stack_space_used = (int)(p2 - p1);
}

(Note: the function declares a local variable which is only a byte, but the compiler will generally allocate an entire machine word for it on the stack.)

So, this will tell you how much stack space is taken by a function call. The more local variables you add to a function, the more stack space it will take. Variables defined in different scopes within the function usually don't complicate things, as the compiler will generally allocate a distinct area on the stack for every local variable without any attempt to optimize based on the fact that some of these variables might never coexist.

like image 40
Mike Nakis Avatar answered Sep 27 '22 23:09

Mike Nakis


To calculate the stack usage for the current function you can do something like this:

void MyFunc( void );

void *pFnBottom = (void *)MyFunc;
void *pFnTop;
unsigned int uiStackUsage;

void MyFunc( void )
{
    __asm__ ( mov pFnTop, esp );
    uiStackUsage = (unsigned int)(pFnTop - pFnBottom);
}
like image 30
Jim Fell Avatar answered Sep 27 '22 23:09

Jim Fell