Main Content

Maximum Stack Usage

Total size of local variables in function plus maximum stack usage from callees

Description

Note

Support for computing code metrics in Code Prover will be removed in a future release. See Version History.

This metric is reported in a Code Prover analysis only.

This metric provides a conservative estimate of the stack usage by a function. The metric is the sum of these sizes in bytes:

  • Higher Estimate of Size of Local Variables

  • Maximum value from the stack usages of the function callees. The computation uses the maximum stack usage of each callee.

    For instance, in this example, the maximum stack usage of func is the same as the maximum stack usage of func1 or func2, whichever is greater.

    void func(void) {
        func1();
        func2();
    }

    If the function calls are in different branches of a conditional statement, this metric considers the branch with the greatest stack usage.

    The analysis does the stack size estimation later on when it has resolved which function calls actually occur. For instance, if a function call occurs in unreachable code, the stack size does not take the call into account. The analysis can also take into account calls through function pointers.

Your actual stack usage can be different from the metric value.

  • Some of the variables are stored in registers instead of on the stack.

  • Your compiler performs variable liveness analysis to enable certain memory optimizations. When estimating this metric, Polyspace® does not consider these optimizations.

  • Your compiler uses additional memory during a function call. For instance, compilers store the address to which the execution returns following the function call. When estimating this metric, Polyspace does not consider this hidden memory usage.

  • Compilers optimize temporary variables in different ways. This metric excludes temporary variables. Only the variables that are explicitly declared by the user are considered.

However, the metric provides a reasonable estimate of the stack usage.

To determine the sizes of basic types, the software uses your specifications for Target processor type (-target). The metric takes into account #pragma pack directives in your code.

Examples

expand all

double func(int);
double func2(int);


double func(int status) {
    double res = func2(status);
    return res;
}


double func2(int status) {
    double res;
    if(status == 0) {
      int temp;    
      res = 0.0;
    }
    else {
      double temp;
      res = 1.0;
    }
    return res;
}

In this example, assuming four bytes for int and eight bytes for double, the maximum stack usages are:

  • func2: 32 bytes

    This value includes the sizes of its parameter (4 bytes), local variable res (8 bytes), local variable temp counted twice (4+8=12 bytes), and return value (8 bytes).

    The metric does not take into account that the first temp is no longer live when the second temp is defined.

  • func: 52 bytes

    This value includes the sizes of its parameter, local variable res, and return value, a total of 20 bytes. This value includes the 32 bytes of maximum stack usage by its callee, func2.

void func1(int);
void func2(void);



void func(int status) {
    func1(status);
    func2();
}


void func1(int status) {
    if(status == 0) {
      int val;
    }
    else {
      double val2;
    }
}


void func2(void) {
    double val;
}

In this example, assuming four bytes for int and eight bytes for double, the maximum stack usages are:

  • func1: 16 bytes

    This value includes the sizes of its parameter (4 bytes) and local variables val and val2 (4+8=12 bytes).

  • func2: 8 bytes

  • func: 20 bytes

    This value includes the sizes of its parameter (4 bytes) and the maximum of stack usages of func1 and func2 (16 bytes).

void func1(void);
void func2(void);


void func(int status) {
    if(status==0)
        func1();
    else
        func2();
}

void func1(void) {
    double val;
}


void func2(void) {
    int val;
}

In this example, assuming four bytes for int and eight bytes for double, the maximum stack usages are:

  • func1: 8 bytes

  • func2: 4 bytes

  • func: 12 bytes

    This value includes the sizes of its parameter (4 bytes) and the maximum stack usage from the two branches (8 bytes).

#include <stdarg.h>


void fun_vararg(int x, ...) {
  va_list ap;
  va_start(ap, x);
  int i;
  for (i=0; i<x; i++) {
    int j = va_arg(ap, int);
  }
  va_end(ap);
}



void call_fun_vararg1(void) {
  long long int l = 0;
  fun_vararg(3, 4, 5, 6, l);
}



void call_fun_vararg2(void) {
  fun_vararg(1,0);
}

In this function, fun_vararg is a function with variable number of parameters. The maximum stack usage of fun_vararg takes into account the call to fun_vararg with the maximum number of arguments. The call with the maximum number of arguments is the call in call_fun_vararg1 with five arguments (one for the fixed parameter and four for the variable parameters). The maximum stack usages are:

  • fun_vararg: 36 bytes.

    This value takes into account:

    • The size of the fixed parameter x (4 bytes).

    • The sizes of the variable parameters from the call with the maximum number of parameters. In that call, there are four variable arguments: three int and one long long int variable (3 times 4 + 1 times 8 = 20 bytes).

    • The sizes of the local variables i, j and ap (12 bytes). The size of the va_list variable uses the pointer size defined in the target (in this case, 4 bytes).

  • call_fun_vararg1: 44 bytes.

    This value takes into account:

    • The stack size usage of fun_vararg with five arguments (36 bytes).

    • The size of local variable l (8 bytes).

  • call_fun_vararg2: 20 bytes.

    Since call_fun_vararg2 has no local variables, this value is the same as the stack size usage of fun_vararg with two arguments (20 bytes, of which 12 bytes are for the local variables and 8 bytes are for the two parameters of fun_vararg).

Metric Information

Group: Function
Acronym: MAX_STACK
HIS Metric: No

Version History

Introduced in R2017b

expand all