Main Content

AUTOSAR C++14 Rule A5-1-4

A lambda expression object shall not outlive any of its reference-captured objects

Description

Rule Definition

A lambda expression object shall not outlive any of its reference-captured objects.

Rationale

The rule flags cases where a lambda expression captures an object by reference and you can potentially access the captured object outside its scope. This situation happens if the lambda expression object outlives the object captured by reference.

For instance, consider this function createFunction:

std::function<std::int32_t()> createFunction() {
   std::int32_t localVar = 0;
   return ([&localVar]() -> std::int32_t {
       localVar = 1;
       return localVar;
   });
}

createFunction returns a lambda expression object that captures the local variable localVar by reference. The scope of localVar is limited to createFunction but the lambda expression object returned has a much larger scope.

This situation can result in an attempt to access the local object localVar outside its scope. For instance, when you call createFunction and assign the returned lambda expression object to another object aFunction:

auto aFunction = createFunction();
and then invoke the new object aFunction:
std::int32_t someValue = aFunction();
the captured variable localVar is no longer in scope. Therefore, the value returned from aFunction is undefined.

If a function returns a lambda expression, to avoid accessing a captured object outside its scope, make sure that the lambda expression captures all objects by copy. For instance, you can rewrite createFunction as:

std::function<std::int32_t()> createFunction() {
   std::int32_t localVar = 0;
   return ([localVar]() mutable -> std::int32_t {
       localVar = 1;
       return localVar;
   });
}

Troubleshooting

If you expect a rule violation but Polyspace® does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

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

auto createMultiplier(int amountToMultiply) {
  int multiplyThis = amountToMultiply; //Compliant
  auto adder = [=] (int initialAmount) {
      return (initialAmount + multiplyThis);
  };
  return adder;
}


void bar() {
  auto MultiplyByTwo = createMultiplier(2);
  int res = MultiplyByTwo(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 AddByTwo, which is 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.

The issue does not occur with the createMultiplier function, which returns a lambda expression that captures local variables by copy.

Check Information

Group: Expressions
Category: Required, Automated

Version History

Introduced in R2019b