CERT C++: EXP61-CPP

Объект lambda не должен переживать ни один из полученных объектов своей ссылки

Описание

Управляйте определением

Объект lambda не должен переживать ни один из полученных объектов своей ссылки. [1]

Примеры

развернуть все

Описание

Проблема происходит, когда лямбда-выражение получает объект ссылкой, и объект лямбда-выражения переживает полученный объект. Например, полученный объект является локальной переменной, но объект лямбда-выражения имеет намного больший осциллограф.

Риск

Если объект лямбда-выражения переживает один из полученных объектов своей ссылки, к полученному объекту можно получить доступ вне его осциллографа.

Например, рассмотрите этот функциональный 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 isundefined.

Фиксация

Если функция возвращает лямбда-выражение, чтобы не получать доступ к полученному объекту вне его осциллографа, убедитесь, что лямбда-выражение получает все объекты копией. Например, можно переписать createFunction как:

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

Пример – указатель на Escape локальной переменной через лямбда-выражение

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

В этом примере, createAdder функция задает лямбда-выражение adder это получает локальную переменную addThis ссылкой. Осциллограф addThis ограничивается createAdder функция. Когда объект, возвращенный createAdder называется, ссылка на переменную addThis получен доступ вне его осциллографа. Когда получено доступ таким образом, значение addThis isundefined.

Коррекция – получает локальные переменные копией в лямбда-выражении вместо ссылки

Если функция возвращает объект лямбда-выражения, постарайтесь не получать локальные переменные ссылкой в объекте lambda. Получите переменные копией вместо этого.

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

Проверяйте информацию

Группа: 02. Выражения (EXP)

Введенный в R2019b


[1]  Это программное обеспечение было создано MathWorks, включающим фрагменты: “Веб-сайт SEI CERT-C”, © 2017 Carnegie Mellon University, веб-сайт SEI CERT-C © 2017 Carnegie Mellon University”, CERT SEI C Кодирование Стандарта – Правил для Разработки безопасных, Надежных и Защищенных систем – 2 016 Выпусков”, © 2016 Carnegie Mellon University, and “CERT SEI Стандарт Кодирования C++ – Правил для Разработки безопасных, Надежных и Защищенных систем на C++ – 2 016 Выпусков” © 2016 Carnegie Mellon University, со специальным разрешением от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ-МЕЛЛОН И/ИЛИ ЕГО ИНСТИТУТА ПРОГРАММНОЙ ИНЖЕНЕРИИ СОДЕРЖАЛ, ЗДЕСЬ ПРЕДОСТАВЛЯЕТСЯ НА ОСНОВЕ "ASIS". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

Это программное обеспечение и сопоставленная документация не были рассмотрены, ни являются подтвержденным Университетом Карнеги-Меллон или его Институтом программной инженерии.