Main Content

Determination of Program Stack Usage

A Polyspace® Code Prover™ analysis can estimate the stack usage of your entire program and each function in your program. The analysis uses the function call hierarchy of your program to estimate stack usage:

  • The stack usage of an individual function is the sum of local variable sizes in the function plus the maximum stack usage from function callees.

  • The stack usage of the entire program is the stack usage of the function at the top of the call hierarchy. Typically, the main() function is at the top of the call hierarchy.

For instance, in this call hierarchy, the stack usage of func is the size of the local variables in func plus the maximum stack usage from func1 and func2 (unless they are called in mutually exclusive branches of a conditional statement).

A snapshot of the Call Hierarchy pane showing the function 'func' with two callees, 'func1' and 'func2'.

For details, see:

Calculate Stack Usage

To calculate stack usage, enable the necessary option before starting a Code Prover analysis:

  • In the Polyspace desktop UI, in the Configuration pane, select the Code Prover Verification > Check Behavior node. Select the Calculate Stack Usage check box.

  • At the command line, use the option Calculate stack usage (-stack-usage).

For more information, see Calculate Stack Usage.

After you run an analysis, Code Prover reports the stack usage metrics along with other results. If you group the results by family on the Results List pane, the stack usage metrics appear under the Code Metrics node.

Investigate Possible Stack Overflow

If your stack usage exceeds available stack space, you can identify which function is responsible. Begin at the main() function and navigate your program call tree. During navigation, look for the function that reports a large size of local variables. If you cannot identify such a function, look for a long call sequence. The steps for navigation are:

  1. On the Source pane, select the main() function. On the Call Hierarchy pane, you see the functions called from main() (callees). To see the full hierarchy, right-click a function and expand all nodes.

    If the Call Hierarchy pane is not open by default, select Window > Show/Hide View > Call Hierarchy.

    A snapshot of the Call Hierarchy pane showing all functions called directly or indirectly from the 'main' function. Double-click the function 'func2' to navigate to its definition in the source code.

  2. To navigate to the callee definition in your source, on the Call Hierarchy pane, double-click each callee name. Then, click the callee name on the Source pane. The Result Details pane shows the higher estimate of local variable size and stack usage by the callee.

    A snapshot of the Result Details pane showing all code metrics for the function 'func2' including its maximum stack usage,

Stack Usage Not Computed

For Code Prover to compute function stack usage, the analysis must be able to reach the end of the function. The following can prevent the computation of function stack usage:

  • Red checks.

    Because Code Prover does not analyze code following a red check, stack usage of a function is not computed if a definite run-time error occurs in the function or one of its callees. If the unanalyzed code contains function calls, any stack usage estimate for the caller function is inaccurate.

    In this example, the function func() contains a red overflow. Code Prover does not analyze the code following the run-time error and does not compute the stack usage of func. If the stack usage was computed, function calls in the unanalyzed code, such as the call to func2, would not be part of the computation.

    #include <limits.h>
    void func(void) {
        int val=INT_MAX;
        val++;
        func2();
    }

  • Infinite loops.

    Loops that are definitely infinite are typically shown through a red Non-terminating loop check. If the loop is trivially infinite, for instance, while(1), instead of a red check, a dashed red underlining appears on the loop keyword. The tooltip on the keyword shows that the loop has been detected as infinite.

  • Recursive functions.

    If a function calls itself directly or indirectly, Code Prover does not compute the stack usage of the function or the stack usage of all functions that call the function.

    If a program contains recursive functions, the program minimum stack usage might be computed even if the maximum stack usage is not. In this case, the program minimum stack usage computation uses an execution path that bypasses the call to the recursive function and might not be an accurate representation of the stack usage.

If the program stack usage is not computed, make sure that the stack usage values of all functions are computed. In the Information column on the Results List pane, check if a function stack usage result shows the value Not computed.

Stack Usage Assumptions

If a function is called but not defined in the code that you provide to Polyspace, the stack usage determination does not take the function call into account. In other words, the contribution to stack size from stubbed functions is assumed to be zero. You can explicitly specify a stack size contribution from such stubbed functions using the option -code-behavior-specifications.

This assumption applies to:

  • Implicit C++ constructors.

    For instance, in this example, func() calls the constructor of class myClass when myObj is defined. Stack usage determination does not consider the constructor as a callee of func().

    class myClass {std::string str;};
    
    void func() {
       myClass myObj;
    }

  • Standard library functions or other functions whose definitions are missing from the code in your Polyspace project.

    For instance, in this example, func calls the standard library function cos(). Unless you provide the definition of cos(), stack usage determination does not consider cos() as a callee of func().

    #include <math.h>
    
    double func(double arg) {
       return cos(arg);
    }

See Also

| | | | | |