18

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.

18
  • 2
    You can. You need to find document that describes ABI for the platform you are using and language mappings for a given language type. After that you need to dig into your compiler's documentation and find implementation details on organizing stack frames and optimizing out automatic variables. After reading all that stuff you will simply generate assembly output and see how stack pointer is actually used, because otherwise it is tedious and inaccurate... Commented Feb 12, 2015 at 22:00
  • 1
    I haven't tried this, but one idea that comes to mind if you want to discover this dynamically, say for a recursive call hierarchy, is to call a function before the one you are interested in, which allocates a very large stack buffer and initializes it to a known pattern, like [0,1,2,3,4,5,6...,0,1,2,3,4,5...] and then call a companion function afterwards, which checks how much of the known pattern is still intact. This would not be accurate down to the byte, of course, but could give a ballpark idea about the stack usage. Commented Feb 12, 2015 at 22:02
  • "simply generate assembly output and see how stack pointer is actually used" If you're compiling with gcc, you can use the -S option to generate an assembly file from your .c file, which you can examine with any text editor. The other option is to use a debugger that shows you the assembly code. That way, you can step through the code and see how the stack pointer and base pointer are used. Commented Feb 12, 2015 at 22:05
  • 1
    why you want to optimize stack usage? it's weird, since it is not necessary to have stack implementation according c standard. even if there is, how stack is used is totally depends on the compiler and os, Commented Feb 12, 2015 at 22:06
  • 2
    @ideasman42 You could look through your compiler manual for compiler specific features. e.g. if you use gcc, you can have it tell you the stack usage of each of your functions with the -fstack-usage flag - you'll have to calculate the usage of the call-graph yourself though (such as if the function is recursive, multiply it with the number of recursions.) Commented Feb 12, 2015 at 22:43

3 Answers 3

14

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.

Sign up to request clarification or add additional context in comments.

3 Comments

i tried to use -fstack-usage flag but i get compiler error. can you provide an example how to use this flag ?
@Karan2020 please post a link to your reference
@vlad_tepesch Reference link gcc.gnu.org/onlinedocs/gnat_ugn/… is already posted in the answer. I have passed the option to GCC compiler. For Example: gcc -c file_name.c -fstack-usage .
2

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);
}

2 Comments

Can you also define pFnBottom and pFnTop inside myFunc?
@étale-cohomology Possibly, but that could affect your function's stack usage. Even using the register keyword doesn't guarantee that your variables will be stored in registers. The most reliable way is to use the implementation shown with global variables. You could declare them as static to limit their scope.
2

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.

18 Comments

I was considering to do something like this, but your example is a bit simplistic. In that the function may have loops, multiple vars defined in different branches, call inline functions... its not always as simple as adding a single variable at the end of a block and getting its address, Also, its possible the compiler re-orders variables - stackoverflow.com/questions/238441/…
No, I repeat, most compilers don't care whether you define them all in one block, or each in its own block. Try it.
@ddriver branches are completely irrelevant. Most compilers will allocate stack space for locals as if they were all declared in the root scope of the function. Don't believe me? Try it. I posted the code. It is so simple. Try it.
@MikeNakis Not all compilers optimize equally.
@JimFell "don't do it this way because the compiler might have a bug" is not a valid argument.
|

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.