【问题标题】:Why this pointer captured by lambda is corrupted while other variable is not为什么 lambda 捕获的此指针已损坏而其他变量未损坏
【发布时间】:2014-09-17 15:38:28
【问题描述】:

我已编译 (g++ -std=c++11 a.cpp) 并运行以下代码:

#include <iostream>
#include <functional>

using namespace std;

class A {
    std::function<void(void)> f;
public:
    A(std::function<void(void)> pf) : f(pf) {}
    void callf() { f(); }
};

class B {
    A *a;
public:
    void test() {
        B *that = this;
        auto f = [this, that]() {
            cout << "this: " << this << " that: " << that << endl;
            delete this->a;
            cout << "this: " << this << " that: " << that << endl;
        };

        a = new A(f);
        a->callf();
    }
};

int main()
{
    B().test();
}

它的输出是:

this: 0x7fff158c88f0 that: 0x7fff158c88f0
this: 0x1ea3000 that: 0x7fff158c88f0

我不明白为什么捕获的这个改变了它的值,而具有不同名称的相同指针没有损坏。

编辑:

我知道 lambda 已被破坏并且我正在生成 UB,但我不明白为什么一个变量已损坏而其他变量未损坏。我不了解这种行为背后的低级细节,顺便说一句,这是非常一致的。我想了解导致这种行为的 gcc 实现细节。

我的进一步调查表明,将 auto f = [this, that] 更改为 auto f = [that, this] 会导致其损坏。

【问题讨论】:

    标签: c++ pointers c++11 lambda


    【解决方案1】:

    未定义的行为,初始化。您刚刚销毁了正在执行的 lambda。

    【讨论】:

    • 我不明白我破坏了包含捕获变量的类(这是 lamda),但是为什么它是一致的行为,这是被破坏而那不是。
    • @Trismegistos,未定义的行为可以是一致的。或者可能不一致。
    • 谁知道?也许~function() 对它以前占用的内存做了一些事情。或者,cout 链中的某些东西正在重新占用以前由 *a 占用的内存并在那里存储新数据。
    • @Trismegistos 此外,未定义的行为并不总是具有简单的“低级”原因,例如某些字节的内存被覆盖。在某些情况下,也可能是因为编译器可能生成的代码仅在不发生 UB 的假设下才尝试做正确的事情。
    • 在其成员函数之一运行时销毁对象不会调用未定义的行为。在对象被销毁后引用它。
    【解决方案2】:

    您正在调用delete this-&gt;a;this-&gt;a 是持有f,导致UB。

    【讨论】:

    • 我知道,但为什么一个变量损坏而另一个没有。
    • 追逐UB,特别是当它处理释放的内存位置的内容时并不是很有意义。此行为将不可移植,并且取决于各种因素。它甚至可能无法在您的机器上完全重现。
    • 即使“在你的机器上”也太笼统了:在你的确切实现上(包括使用的特定编译器选项)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-06
    • 1970-01-01
    相关资源
    最近更新 更多