Main Content

CERT C++: DCL30-C

Declare objects with appropriate storage durations

Description

Rule Definition

Declare objects with appropriate storage durations.1

Polyspace Implementation

The rule checker checks for Pointer or reference to stack variable leaving scope.

Examples

expand all

Issue

Pointer or reference to stack variable leaving scope occurs when a pointer or reference to a local variable leaves the scope of the variable. For instance:

  • A function returns a pointer to a local variable.

  • A function performs the assignment globPtr = &locVar. globPtr is a global pointer variable and locVar is a local variable.

  • A function performs the assignment *paramPtr = &locVar. paramPtr is a function parameter that is, for instance, an int** pointer and locVar is a local int variable.

  • A C++ method performs the assignment memPtr = &locVar. memPtr is a pointer data member of the class the method belongs to. locVar is a variable local to the method.

The defect also applies to memory allocated using the alloca function. The defect does not apply to static, local variables. Polyspace® assumes that the local objects within a function definition are in the same scope.

Risk

Local variables are allocated an address on the stack. Once the scope of a local variable ends, this address is available for reuse. Using this address to access the local variable value outside the variable scope can cause unexpected behavior.

If a pointer to a local variable leaves the scope of the variable, Polyspace Bug Finder™ highlights the defect. The defect appears even if you do not use the address stored in the pointer. For maintainable code, it is a good practice to not allow the pointer to leave the variable scope. Even if you do not use the address in the pointer now, someone else using your function can use the address, causing undefined behavior.

Fix

Do not allow a pointer or reference to a local variable to leave the variable scope.

Example - Pointer to Local Variable Returned from Function
void func2(int *ptr) {
    *ptr = 0;
}

int* func1(void) {
    int ret = 0; //Noncompliant
    return &ret ;
}
void main(void) {
    int* ptr = func1() ;
    func2(ptr) ;
}

In this example, func1 returns a pointer to local variable ret.

In main, ptr points to the address of the local variable. When ptr is accessed in func2, the access is illegal because the scope of ret is limited to func1,

Example - Pointer to Local Variable Escapes Through Lambda Expression
auto createAdder(int amountToAdd) {
  int addThis = amountToAdd;  //Noncompliant
  auto adder = [&] (int initialAmount) {
      return (initialAmount + addThis);
  };
  return adder;
}
 
void func() {
  auto AddByTwo = createAdder(2);
  int res = AddByTwo(10);
}

In this example, the createAdder function defines a lambda expression adder that captures the local variable addThis by reference. The scope of addThis is limited to the createAdder function. When the object returned by createAdder is called, a reference to the variable addThis is accessed outside its scope. When accessed in this way, the value of addThis is undefined.

Correction – Capture Local Variables by Copy in Lambda Expression Instead of Reference

If a function returns a lambda expression object, avoid capturing local variables by reference in the lambda object. Capture the variables by copy instead.

Variables captured by copy have the same lifetime as the lambda object, but variables captured by reference often have a smaller lifetime than the lambda object itself. When the lambda object is used, these variables accessed outside scope have undefined values.

auto createAdder(int amountToAdd) {
  int addThis = amountToAdd;
  auto adder = [=] (int initialAmount) {
      return (initialAmount + addThis);
  };
  return adder;
}
 
void func() {
  auto AddByTwo = createAdder(2);
  int res = AddByTwo(10);
}

Check Information

Group: 01. Declarations and Initialization (DCL)

Version History

Introduced in R2019a

expand all


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.