GCC在lambda中捕获`this`

时间:2016-06-30 12:20:44

标签: c++ gcc lambda

我有一个代码:

#include <cstdio>
#include <functional> 

class test {
public:
    void Do() {
        this->test_fun();
    }

    void Init() {
        this->number = 1008;
        this->test_fun = [this] {
            this->test_fun = nullptr;
            printf("number %d\n", this->number); //gcc crash here, this == nullptr
        };

    }

public:
    std::function<void()> test_fun;
    int number = 0;
};


int main() {
    test t;
    t.Init();
    t.Do();

    return 0;
}

它可以在MSVC2013上运行,但在行上的gcc崩溃:printf("number %d\n", this->number);

我做错了什么?

海湾合作委员会版本:gcc版本4.8.2 20140120(红帽4.8.2-15)(GCC)

1 个答案:

答案 0 :(得分:3)

您的代码引入了未定义的行为,因为lambda的自毁已经

this->test_fun = nullptr;

这个例子应该是等价的:

#include <cstdio>
#include <cassert>
#include <memory>

class test {
public:
    struct Lambda {
        test* this_ptr;
        Lambda(test* this_ptr) : this_ptr(this_ptr) {}
        ~Lambda() {
            this_ptr = nullptr;
        }
        void operator () () {
            printf("this_ptr %p\n", (void*)this_ptr);
            // self destruction
            this_ptr->test_fun = nullptr;
            // undefined behavior starts here ...
            printf("this_ptr %p\n", (void*)this_ptr);
            printf("number %d\n", this_ptr->number);
        }
    };

    void Do() {
        assert(this->test_fun.get());
        (*this->test_fun)();
    }

    void Init() {
        this->number = 1008;
        this->test_fun = std::make_unique<Lambda>(this);
    }

public:
    std::unique_ptr<Lambda> test_fun;
    int number = 0;
};


int main() {
    test t;
    t.Init();
    t.Do();

    return 0;
}