【问题标题】:Abort() when starting up a few threads with std::vector<std::future<int>> and std::async使用 std::vector<std::future<int>> 和 std::async 启动几个线程时 Abort()
【发布时间】:2020-02-02 15:19:58
【问题描述】:

我正在使用 4 个线程使用 thread_local 内存池创建一些对象。

我使用std::vector&lt;std::future&lt;int&gt;&gt;std::async(std::launch::async, function); 来调度线程,并使用std::for_eacht.get 来获取它们的值。代码如下:

struct GameObject
{
    int x_, y_, z_;
    int m_cost;

    GameObject() = default;
    GameObject(int x, int y, int z, int cost)
        : x_(x), y_(y), z_(z), m_cost(cost)
    {}
};

struct Elf : GameObject
{
    Elf() = default;
    Elf(int x, int y, int z, int cost)
        : GameObject(x, y, z, cost)
    {
        std::cout << "Elf created" << '\n';
    }

    ~Elf() noexcept
    {
        std::cout << "Elf destroyed" << '\n';
    }
    std::string m_cry = "\nA hymn for Gandalf\n";
};

struct Dwarf : GameObject
{
    Dwarf() = default;
    Dwarf(int x, int y, int z, int cost)
        : GameObject(x, y, z, cost)
    {
        std::cout << "dwarf created" << '\n';
    }

    ~Dwarf() noexcept
    {
        std::cout << "dwarf destroyed" << '\n';
    }
    std::string m_cry = "\nFind more cheer in a graveyard\n";
};


int elvenFunc()
{
    thread_local ObjectPool<Elf> elvenPool{ 229 };
    for (int i = 0; i < elvenPool.getSize(); ++i)
    {
        Elf* elf = elvenPool.construct(i, i + 1, i + 2, 100);
        std::cout << elf->m_cry << '\n';
        elvenPool.destroy(elf);
    }

    thread_local std::promise<int> pr;
    pr.set_value(rand());

    return 1024;
}

int dwarvenFunc()
{
    thread_local ObjectPool<Dwarf> dwarvenPool{ 256 };
    for (int i = 0; i < dwarvenPool.getSize(); ++i)
    {
        Dwarf* dwarf = dwarvenPool.construct(i - 1, i - 2, i - 3, 100);
        std::cout << dwarf->m_cry << '\n';
        dwarvenPool.destroy(dwarf);
    }

    thread_local std::promise<int> pr;
    pr.set_value(rand());

    return 2048;
}


int main()
{
    std::ios_base::sync_with_stdio(false);
    srand(time(0));

    std::vector<std::future<int>> vec{ 4 };
    vec.emplace_back(std::async(std::launch::async, elvenFunc));
    vec.emplace_back(std::async(std::launch::async, elvenFunc));
    vec.emplace_back(std::async(std::launch::async, dwarvenFunc));
    vec.emplace_back(std::async(std::launch::async, dwarvenFunc));

    int term = 0;
    try
    {
        std::for_each(std::execution::par, vec.begin(), vec.end(), [&term](std::future<int>& t)
        {
            auto ret = t.get();
            std::cout << "thread brought me " << ret << '\n';
            term += ret;
        });
    }
    catch (const std::exception& ex)
    {
        std::cout << ex.what() << '\n';
    }

    std::cout << "Final word = " << term << '\n';
}

constructdestroy 在内部调用 allocatedeallocate。)我从终端得到了很多预期的输出,但是在某处 abort 被调用并且程序没有正常完成。我不知道为什么。我相信以 std::async 启动的线程的t.get() 调用会自动调用.join 对吗?

使用 C++17 和 Visual Studio 2017。我做错了什么?

【问题讨论】:

    标签: c++ multithreading visual-studio c++11 future


    【解决方案1】:

    你有未定义的行为。您在无效的未来致电get。您的期货向量的前 4 个项目为空 futureget 只能在 future::valid 返回 true 时调用。

    你觉得这条线怎么样

    std::vector<std::future<int>> vec{ 4 };
    

    会吗?

    默认构造函数。构造一个没有共享状态的 std::future。 构造后valid() == false。

    here 你可以读到当future::get 被调用时会发生什么:

    如果在调用 this 之前 valid() 为 false,则行为未定义 功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-13
      • 1970-01-01
      • 2020-01-26
      • 1970-01-01
      • 1970-01-01
      • 2020-12-29
      • 2015-08-28
      • 2011-10-29
      相关资源
      最近更新 更多