メインコンテンツ

AUTOSAR C++14 Rule A5-1-4

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

説明

ルール定義

ラムダ式オブジェクトが、自身の参照取得オブジェクトよりも長く存続してはなりません。

根拠

このルールでは、ラムダ式が "参照によって" オブジェクトを取得しており、スコープ外から取得元オブジェクトにアクセスされる可能がある場合にフラグを立てます。この状況は、ラムダ式オブジェクトが参照取得オブジェクトよりも長く存続する場合に発生します。

たとえば、関数 createFunction を考えます。

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

createFunction は、"参照によって" ローカル変数 localVar を取得するラムダ式オブジェクトを返します。localVar のスコープは createFunction に制限されますが、返されたラムダ式オブジェクトはより大きなスコープをもちます。

このような状況では、スコープの外でローカル オブジェクトである localVar に対するアクセスが行われる可能性があります。たとえば、次のように、createFunction を呼び出し、返されたラムダ式オブジェクトを別のオブジェクト aFunction に割り当てるとします。

auto aFunction = createFunction();
次いで、新しいオブジェクトaFunction を呼び出します。
std::int32_t someValue = aFunction();
取得元の変数 localVar はスコープ外です。したがって、aFunction から返される値は未定義となります。

関数がラムダ式を返す場合、取得オブジェクトに対するスコープ外アクセスを防ぐため、そのラムダ式がすべてのオブジェクトをコピーによって取得するようにします。たとえば、createFunction を次のように書き換えることができます。

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

トラブルシューティング

ルール違反が想定されるものの、Polyspace® から報告されない場合は、コーディング規約違反が想定どおりに表示されない理由の診断を参照してください。

すべて展開する

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);
}

この例では、関数 createAdder で、参照によってローカル変数 addThis を取得するラムダ式 adder を定義しています。addThis のスコープは関数 createAdder に制限されます。createAdder によって返された AddByTwo オブジェクトが呼び出されると、変数 addThis に対する参照がスコープ外からアクセスされます。この方法でアクセスが行われると、addThis の値は未定義となります。

この問題は、ローカル変数をコピーによって取得するラムダ式を返す関数 createMultiplier では発生しません。

チェック情報

グループ:
カテゴリ: Required、Automated

バージョン履歴

R2019b で導入