由于移动了承诺而导致的细分错误

时间:2019-03-09 20:01:09

标签: c++11 stdthread std-future

我已经通过了promise作为对线程的引用。之后,promise通过std :: move移到向量中。在执行软件时,这会导致分段错误。

我认为在移动承诺后,线程中的引用永远不会更新吗?如何将承诺传递给线程,以便以后可以移动它?请参阅以下有关我的问题的代码示例。

#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();
    }

}

2 个答案:

答案 0 :(得分:3)

lambda拥有引用的承诺p已从移出,并且超出了范围。您将需要额外的间接级别,以使承诺永远不会动摇。

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);
});

这样,承诺永远不会移动,您只需移动指针即可。 Lambda会定期获得该诺言的指针。

here看到它。

答案 1 :(得分:1)

对于您的问题,我没有答案。至少我还没有。但是,似乎还没有其他答案,我发现您的问题很有趣,所以让我们尝试一下:

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

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

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

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

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

你看到我在那里做什么吗?我通过智能指针间接地实现了诺言的所有权。我们知道,智能指针会优雅地进行破坏,因此此代码不会移动承诺本身,而只会移动指向承诺的指针。但是代码仍然存在段错误。

那么我们确定诺言实际上是导致段错误的原因吗?

也许是诺言确实造成了段错误,但是现在至少我们有了另一种解决问题的方法,除非您已经尝试过了。