Ошибка сегментации из-за сдвинутого обещания - PullRequest
1 голос
/ 09 марта 2019

Я передал обещание как ссылку на поток. После этого обещание было перемещено в вектор с помощью 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 ]

3 голосов
/ 09 марта 2019

Обещание 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);
});

Таким образом, обещание никогда не двигается, вы просто перемещаете указатель. Лямбда получает обычный не владеющий указатель на обещание.

Смотри здесь .

1 голос
/ 09 марта 2019

У меня нет ответа на ваш вопрос. По крайней мере, у меня его еще нет. Однако, никаких других ответов, похоже, еще не появилось, и я считаю, что ваш вопрос интересен, поэтому давайте попробуем это:

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

Ты видишь, что я там делал? Я перенаправил владение обещанием через умный указатель. Мы знаем, что интеллектуальные указатели разрушаются изящно, поэтому само обещание никогда не перемещается этим кодом, а перемещается только указатель на обещание. Тем не менее код по-прежнему segfaults.

Значит, мы уверены, что обещание - это то, что является причиной ошибки segfault?

Может быть, обещание действительно вызывает ошибку, но теперь, по крайней мере, у нас есть другой способ решить проблему - если вы уже не пробовали это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...