c++ - C++:读取 Lambda 捕获的指针时发生访问冲突
问题描述
我不会假装我对 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;
}
};
主代码在创建新的 Object 实例之前执行并首先调用RESET方法。假设“主”代码无法访问、读取或修改 obj - 因此依赖于盲重置。
预期结果:第一次调用重置表达式时,对 obj 的检查应该返回 false,因为 obj 在外部范围内被设置为 nullptr - 没有任何反应。
实际结果:执行reset时,obj不再指向NULL,检查返回true并调用delete,导致访问冲突。
我想知道我尝试做的任何事情是否都是无效的操作,或者我捕获变量的方式是否不正确。我尝试按值捕获指针,将函数设置为可变,并且出于绝望将引用和值捕获相结合。
编辑:在这一点上,我相信对象的范围是其他人指出的罪魁祸首。考虑到这一点,我将尝试解决方法并报告。
解决方案
虽然我们不能仅从您的示例中看出,但我怀疑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;
};
推荐阅读
- python - “类”对象没有属性“ImageTk”
- python-3.x - leetcode 88 合并排序数组 python3 切片问题
- swift - 通过对象的枚举属性使用 NSPredicate 获取核心数据托管对象的问题
- c# - Moq 成员变量不会因设置无效而引发错误
- c# - RESTful API - 为每个实体创建“服务”和“接口”?
- r - 创建一个函数,不小心覆盖了输出
- bash - bash 变量替换和引用
- android - MaterialComponents 主题中断 TabLayout
- python - 如何在 python 中解析包含 HTML 代码的 XLS 文件?
- c# - .net 核心复选框模型绑定视图