Main Content

Minimum Stack Usage

Total size of local variables in function taking nested scopes into account 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 an optimistic estimate of the stack usage by a function. Unlike the metric Maximum Stack Usage, this metric takes nested scopes into account. For instance, if variables are defined in two mutually exclusive branches of a conditional statement, the metric considers that the stack space allocated to the variables in one branch can be reused in the other branch.

The metric is the sum of these sizes in bytes:

  • Lower Estimate of Size of Local Variables.

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

    For instance, in this example, the minimum stack usage of func is the same as the minimum 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 least 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 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 minimum stack usages are:

  • func2: 28 bytes

    This value includes the sizes of its parameter (4 bytes), local variable res (8 bytes), one of the two local variables temp (8 bytes), and return value (8 bytes).

    The metric takes into account that the first temp is no longer live when the second temp is defined. It uses the variable temp with data type double because its size is greater.

  • func: 48 bytes

    This value includes the sizes of its parameter, local variable res, and return value, a total of 20 bytes. This value includes the 28 bytes of minimum 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 minimum stack usages are:

  • func1: 12 bytes

    This value includes the sizes of its parameter (4 bytes) and the larger of the two local variables, in this case, val2 (8 bytes).

  • func2: 8 bytes

  • func: 16 bytes

    This value includes the sizes of its parameter (4 bytes) and the maximum of stack usages of func1 and func2 (12 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 minimum stack usages are:

  • func1: 8 bytes

  • func2: 4 bytes

  • func: 8 bytes

    This value includes the sizes of its parameter (4 bytes) and the minimum stack usage from the two branches (4 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 minimum stack usage of fun_vararg takes into account the call to fun_vararg with the minimum number of arguments. The call with the minimum number of arguments is the call in call_fun_vararg2 with two arguments (one for the fixed parameter and one for the variable parameter). The minimum stack usages are:

  • fun_vararg: 20 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 minimum number of parameters. In that call, there is only one variable argument of type int (4 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, of which 12 bytes are for the local variable sizes and 20 bytes are for the fixed and variable parameters of fun_vararg).

    • 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).

Metric Information

Group: Function
Acronym: MIN_STACK
HIS Metric: No

Version History

Introduced in R2017b

expand all