2016-06-17 3 views
0

Следующая тестовая программа компилируется с g++ -o test -pthread -std=c++11 test.cpp просто отлично:Исключение при присоединении темы

#include <iostream> 
#include <vector> 
#include <thread> 
#include <chrono> 

using namespace std; 

void foo(int); 

int main() 
{ 
     vector<thread> threads(5); 
     for (int i = 0; i < 5; i++) 
     { 
       threads.push_back(thread(foo, i)); 
     } 

     for (vector<thread>::iterator iter = threads.begin(); iter != threads.end(); iter++) 
     { 
       iter->join(); 
     } 
} 

void foo(int id) 
{ 
     cout << "thread " << id << " started."; 
     this_thread::sleep_for(chrono::seconds(10)); 
     cout << "thread " << id << " terminated."; 
} 

Однако, при запуске он дает результат, похожий на этот:

terminate called after throwing an instance of 'std::system_error' 
    what(): Invalid argument 
thread thread 2 started.1 started.thread 4 started.thread 3 started.thread 0 started.Aborted (core dumped) 

Я понятия не имею, где эта ошибка исходит из. Из отладки я знаю, что ошибка происходит, как только я пытаюсь присоединиться к первому потоку.
http://www.cplusplus.com/reference/thread/thread/join/ утверждает, что соединение будет только кидать invalid_argument, если поток не соединяется.
http://www.cplusplus.com/reference/thread/thread/joinable/ утверждает, что поток не совмещён только если:

  • он по умолчанию возведенных.
  • он был перемещен из (либо построил другой объект нити, либо назначил ему).
  • Соединился или отсоединился любой из его членов.

Как ясно видно, нить не была построена по умолчанию.
Я никогда не переписываю нить другим объектом нити. Вывод программы также показывает, что каждый поток явно работает, так как начинается «thread x». заявления.
Я звоню только один раз для каждого потока.

Если я сделаю паузу в 5 секунд между созданием и присоединением, я получаю тот же выход, так что это не проблема гонки. Хотя интересно, что вывод по-прежнему упорядочен таким же образом. Есть идеи?

+0

FYI cplusplus.com - это, как известно, ненадежный сайт - я предлагаю вам дважды проверить поведение, в котором вы находитесь, в зависимости от cppreference.com. –

+0

Вы пишете 'cout', который буферизуется до следующего флеша. Затем возникает ошибка, которая записывается в 'cerr' и которая записывается немедленно (без буферизации). Затем, наконец, буферы 'cout' очищаются. BTW: Я не покупаю ваше утверждение, что это «компилирует [...] просто отлично», если вы также не включаете предупреждения! –

ответ

3

Вы не должны назначать vector с 5 потоками, построенными по умолчанию, а затем игнорировать их, а push_back - дополнительные. Затем ваш join пытается присоединиться к потокам и броскам, построенным по умолчанию. Избавьтесь от (5) или переместите его на звонок reserve.

+0

Это сработало! Я не думал о том, что создание с помощью конструкторов по умолчанию вызывает по умолчанию. – RogueCSDev

Смежные вопросы