Следующая тестовая программа компилируется с 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 секунд между созданием и присоединением, я получаю тот же выход, так что это не проблема гонки. Хотя интересно, что вывод по-прежнему упорядочен таким же образом. Есть идеи?
FYI cplusplus.com - это, как известно, ненадежный сайт - я предлагаю вам дважды проверить поведение, в котором вы находитесь, в зависимости от cppreference.com. –
Вы пишете 'cout', который буферизуется до следующего флеша. Затем возникает ошибка, которая записывается в 'cerr' и которая записывается немедленно (без буферизации). Затем, наконец, буферы 'cout' очищаются. BTW: Я не покупаю ваше утверждение, что это «компилирует [...] просто отлично», если вы также не включаете предупреждения! –