移动承诺导致分段错误

问题描述 投票:1回答:2

我已经传递了一个承诺作为线程的引用。之后,承诺通过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();
    }

}
c++11 stdthread std-future
2个回答
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
投票

我对你的问题没有答案。至少,我还没有。然而,似乎还没有其他答案出现,我发现你的问题很有趣,所以让我们试试这个:

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

你看到我在那里做了什么吗?我通过智能指针指向了承诺的所有权。我们知道智能指针优雅地破坏,因此承诺本身永远不会被这个代码移动,但只有指向promise的指针才会被移动。然而,代码仍然是段落错误。

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

也许承诺确实导致了段错误,但现在至少我们有另一种方法来解决问题 - 除非你已经尝试过这个。

© www.soinside.com 2019 - 2024. All rights reserved.