C ++:读取Lambda捕获的指针时的访问冲突

时间:2018-05-23 14:45:35

标签: c++ lambda

我不会假装我对lambdas非常有经验,但是对于这个看似简单的问题,我认为我需要更深入地了解它是如何运作的。

我在外部作用域上实例化一个对象,并使用2个lambdas,我尝试修改该指针。

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

在创建Object的新实例之前,主代码会执行并首先调用 RESET 方法。假设&#34;主要&#34;代码无法访问,读取或修改obj - 因此依赖于盲目重置。

预期结果:第一次调用重置表达式时,对obj的检查应返回false,因为obj在外部作用域中设置为nullptr - 没有任何反应。

实际结果:执行重置时,obj不再指向NULL,检查返回true并调用delete,导致访问冲突。

我想知道我试图做的是一个无效的操作,或者我捕获变量的方式是否不正确。我尝试按值捕获指针,将函数设置为可变,以及绝望的参考和值捕获的组合。

  

编辑:此时,我认为对象的范围是其他人指出的主要罪魁祸首。我将尝试解决方法   记住并报告回来。

1 个答案:

答案 0 :(得分:1)

虽然我们无法单独从您的示例中看出,但我怀疑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;
};