C ++: нарушение прав доступа при чтении указателя, захваченного Lambda - PullRequest
0 голосов
/ 23 мая 2018

Я не собираюсь притворяться, что у меня очень большой опыт работы с лямбдами, но с этой, казалось бы, простой проблемой, я думаю, мне нужно более глубокое понимание того, как это на самом деле работает.

Я создаю экземпляр объекта во внешней области видимости,и используя 2 лямбда-выражения, я пытаюсь изменить этот указатель.

// Object to be manipulated
Object* obj= nullptr;

// To be invoked externally in order to construct and initialize obj
std::function<void(std::function<void(const String&)>)> SetObject
    = [&obj](std::function<void(const String&)> func) 
{
    obj= new Object();
    // ... Initialize Values
};

// To be invoked externally to reset and delete obj
std::function<void()> ResetObject
= [&obj]() 
{
    if(obj)
    {
        delete obj;
        obj= nullptr;
    }
};

Основной код выполняется и сначала вызывает метод RESET перед созданием нового экземпляра Object.Предположим, что «основной» код не имеет доступа к чтению или изменению obj, следовательно, полагается на слепой сброс.

Ожидаемый результат : При первом вызове выражения сброса,проверка obj должна возвращать false, потому что для obj было установлено значение nullptr во внешней области - ничего не происходит.

Фактический результат: К моменту сброса времени obj больше не указывает на NULL, проверка возвращает true и вызывается delete, что вызывает нарушение прав доступа.

Я хотел бы знать, является ли то, что я пытаюсь сделать, недопустимой операцией для начала, или то, как я собираю свои данные?переменные неверны.Я попытался захватить указатель по значению, установив функцию непостоянным, и комбинацию ссылки и захвата значения из отчаяния.

РЕДАКТИРОВАТЬ: На данный момент, я считаю,сфера охвата объекта является основным виновником, на что указывают другие.Я попытаюсь обойти эту проблему и доложу.

1 Ответ

0 голосов
/ 23 мая 2018

Хотя мы не можем судить только по вашему примеру, я подозреваю, что obj, возможно, является локальной переменной, которая выходит из области видимости после захвата.Один из способов решить эту проблему - добавить еще один уровень косвенности:

Object** objptr = new Object*();

std::function<void(std::function<void(const String&)>)> SetObject
    = [objptr](std::function<void(const String&)> func) 
{
    *objptr = new Object();
};

std::function<void()> ResetObject
= [objptr]() // Note we are now capturing objptr by value
{
    if(*objptr)
    {
        delete *objptr;
        *objptr = nullptr;
    }
    // Is objptr reused by another call to SetObject?
    // If not, delete it here as well.
    // delete objptr;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...