12

C++11 でマルチスレッド コードを実行すると問題 (segfault) が発生しました。ここにコードがあります:

#include <vector>
#include <thread>

std::vector<int> values;
int i;

void values_push_back()
{
    values.push_back(i);
}

int main()
{
    while(true)
    {
        std::vector<std::thread> threads;

        for(i=0; i<10; ++i)
        {
            std::thread t(values_push_back);
            threads.push_back(std::move(t));
        }
        for(i=0; i<10; ++i)
            threads[i].join();
    }

    return 0;
}

そして、ここで gdb のバックトレース: http://pastebin.com/5b5TN70c

それの何が問題なのですか?

4

1 に答える 1

20

これは移動とは関係ありません。

複数のスレッドがvector::push_back()同じ上で実行されていますvectorvector::push_back()、スレッドセーフではありません。変更はvector同期する必要があります。

Astd::mutexを使用して、次の呼び出しを同期できますpush_back()

std::vector<int> values;
std::mutex values_mutex;

void values_push_back()
{
    values_mutex.lock();
    values.push_back(i);
    values_mutex.unlock();
}

また、変数iは同期なしでスレッド間で共有されているため、競合状態が発生する可能性があります(これにより、重複intが追加される可能性がありvectorます)。intこれを回避するために、引数として値をスレッドに渡すことを検討してください。

std::vector<int> values;
std::mutex values_mutex;

void values_push_back(int i)
{
    values_mutex.lock();
    values.push_back(i);
    values_mutex.unlock();
}

for (int i = 0; i < 10; ++i)
{
    threads.push_back(std::thread(values_push_back, i));
}

for (auto& t: threads) t.join();

バンボンがコメントしたように、スローstd::lock_guardされた場合にロックが解放されることを保証することを好みますpush_back()(この場合のみ可能ですbad_alloc()が、vectorスローコンストラクターを持つより複雑なオブジェクトを保持するための変更がより重要になります):

void values_push_back(int i)
{
    std::lock_guard<std::mutex> lk(values_mutex);
    values.push_back(i);
}
于 2013-02-13T17:29:50.933 に答える