C++ lambda 表达式 : captured pointer to STL container changing address after pop?

标签 c++ pointers c++11 lambda

我想弄清楚为什么下面的代码会中断。在lambda表达式中调用objects->pop();后,Visual Studio调试时objects的内存地址变为0xfeeefeee。我可以通过在 pop 之前执行 auto p = objects; 来解决这个问题,然后在第二行使用 p 而不是 objects lambda 。但是,我必须在这里遗漏一些基本的东西。

class Obj
{
public:
    Obj(stack<shared_ptr<Obj>>* const objects) {
        fun = [=] {
            objects->pop(); // objects' address changed after this executes
            objects->push(shared_ptr<Obj>(new Obj(objects)));
        };
    }

    function<void(void)> fun;
};

int main()
{
    stack<shared_ptr<Obj>> objects;
    objects.push(shared_ptr<Obj>(new Obj(&objects)));
    objects.top().get()->fun();
    return 0;
}

最佳答案

您正在观察的是 undefined behavior .

捕获的内存objects调用 objects->pop(); 时释放变量占用一个很好的提示是它更改为的值: 0xFEEEFEEE .这个魔数(Magic Number)表示释放的内存。

让我们分析一下会发生什么。

stack<shared_ptr<Obj>> objects;
objects.push(shared_ptr<Obj>(new Obj(&objects)));

A stackshared_ptr的被创建。推到它上面的是一个新的 Obj实例,其构造函数参数是指向我们的 stack 的指针.

Obj(stack<shared_ptr<Obj>>* const objects) {
    fun = [=] { 
       /* ... */
    };
}

A function对象被分配了一个 lambda,它捕获了 objects争论。

objects.top().get()->fun();调用函数对象:

objects->pop(); // objects' address changed after this executes 

objects的栈顶元素指向,是Obj fun 的实例对象所属。通过弹出它,shared_ptr 的唯一(也是最后一个)实例持有对它的引用超出范围并释放它使用的内存。这包括捕获的指向 objects 的指针.在调试版本中 HeapFree将其设置为 0xFEEEFEEE .在发布版本中,任何事情都可能发生。在此之后,您将引用已释放的内存,这是未定义的行为。

关于C++ lambda 表达式 : captured pointer to STL container changing address after pop?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23008198/

相关文章:

c++ - 使用 Solaris CC 的 std::BinaryPredicate 问题

c++ - 在巴比伦算法中为 C++ 中的平方根获取无限循环

C 列表的实现

c++ - 如何遍历 std::tuple?

c++ - 用 boost 写一个 gz 流

c++ - 使用opencv跟踪边界

c++ - 将变量 N​​AME 传递给函数

c - 在 c 中的多行 printf 后,程序以段错误(核心转储)结束?

c++ - nullptr 可以用作类型吗?

c++ - 终止在无限循环中运行的 std::thread