Search code examples
c++11stdthreadstd-future

Segmentation fault because of moved promise


I've passed a promise as a reference to a thread. Afterwards, the promise was moved into a vector via std::move. This is causing a segmentation fault when the software is executed.

I reckon the reference in the thread is never updated after moving the promise? How can I pass the promise to the thread so that I can move it afterwards? Please see the following code example of my problem.

#include <iostream>
#include <thread>
#include <vector>
#include <future>


class Test {        
    public:
    std::thread t;
    std::promise<int> p;
    Test(std::thread&& rt, std::promise<int>&& rp) : t(std::move(rt)), p(std::move(rp)) {}
};

int main()
{
    std::vector<Test> tests;

    {
        auto p = std::promise<int>();
        std::thread t ([&p]{
            std::cout << 1;
            p.set_value(1);
        });
        tests.push_back(Test(std::move(t), std::move(p)));
    }  

    for(Test& mytest : tests)
    {
        mytest.t.join();
    }

}

Solution

  • The promise p that the lambda holds a reference to is moved from and goes out of scope. You'll need an extra level of indirection so that the promise never moves.

    auto pp = std::make_unique<std::promise<int>>();
    std::thread t ([p = pp.get()] { // <--- p is a promise<int>*
        std::cout << 1;
        p->set_value(1);
    });
    

    This way, the promise never moves, you just move the pointer. The lambda gets a regular non-owning pointer to the promise.

    See it here.