【问题标题】:C++: Access Violation when reading pointer captured by LambdaC++:读取 Lambda 捕获的指针时发生访问冲突
【发布时间】:2018-11-02 14:51:18
【问题描述】:

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

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

// 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 -- 没有任何反应。

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

我想知道我正在尝试做的任何事情是否一开始就是一个无效的操作,或者我捕获变量的方式是否不正确。我尝试按值捕获指针,将函数设置为可变,并出于绝望将引用和值捕获相结合。

编辑:在这一点上,我相信对象的范围是其他人指出的罪魁祸首。我将尝试解决方法 记住这一点并报告回来。

【问题讨论】:

  • 当 lambda 被调用时,obj 是否超出范围?
  • 是的,我们确实需要知道该声明的范围。 MCVE 会让这一点显而易见。
  • 请编辑您的问题以包含minimal reproducible example
  • 对不起,我试图尽可能地精简它,因为我不允许共享此代码的上下文。我可以说我展示的代码(以及许多其他 lambda 表达式)位于应用程序首次运行时调用的初始化函数中。如果信息不足,请随时删除问题。
  • 是否有充分的理由不能将obj 换成智能指针,即std::unique_ptr&lt;Object&gt;

标签: c++ lambda


【解决方案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;
};

【讨论】:

  • 那么,这是因为我们通过 VALUE 捕获了 objptr - 否则,它会属于与原始示例相同的范围问题吗?
猜你喜欢
  • 2022-01-10
  • 2018-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多