Я изучаю многопоточность на C++, используя pthread, на Tutorials Point (может быть, он старый, но мне просто нужно что-то начать). Я изменил код немного:Многопоточность C++: завершение после бросания экземпляра 'std :: length_error'
#include <pthread.h>
#include <iostream>
#include <string>
#define NUM_THREADS 5
#define DEBUG
#undef DEBUG
using namespace std;
struct thread_data {
int thread_id = 0;
string message = "";
};
void *printHello(void *threadData)
{
struct thread_data* data = (struct thread_data*)threadData;
int thread_id = data->thread_id;
string message = data->message;
cout << "From thread " << thread_id << ": " << message << "\n";
pthread_exit(NULL);
}
int main(int argc, char** argv)
{
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
struct thread_data* data = new thread_data();
string message = "Special message for thread #" + to_string(i) + "!";
#ifdef DEBUG
cout << "DEBUG: " << "i = " << i << endl;
#endif
data->thread_id = i;
data->message = message;
cout << "main(): creating thread, " << i << endl;
int rc = 0;
rc = pthread_create(&threads[i], NULL, printHello, (void *) data);
delete data;
if (rc) {
cout << "Error: unable to create thread: " << rc << "\n";
return -1;
}
}
pthread_exit(NULL);
}
Я скомпилированного:
g++ -pthread -g -Wall -std=c++11 main.cpp -o main
И выход:
main(): creating thread, 0
main(): creating thread, 1
From thread 1: Special message for thread #1!
main(): creating thread, 2
From thread 2: Special message for thread #2!
main(): creating thread, 3
From thread 3: Special message for thread #3!
main(): creating thread, 4
From thread 4: Special message for thread #4!
terminate called after throwing an instance of 'std::length_error'
what(): basic_string::_S_create
Aborted (core dumped)
Если я не создавать темы, используя pthread_create
и вызов функция printHello напрямую, ошибки не возникает. Иногда программа запускает segfault вместо этого, и иногда она работает гладко!
Другая проблема заключается в том, что с самого начала должна быть строка, указывающая From thread 0: Special message for thread #0!
, но не было.
Кроме того, иногда сообщение «Специальное сообщение для потока #n!» даже не появился.
Я попытался инициализировать переменные структуры, использовать статически выделенную память (стек вместо кучи, не используя new
) в строке 31. Я попытался избежать использования указателей в функции printHello, но так как последний аргумент pthread_create принимает только указатель на аргументы функции, я не мог этого сделать.
Мое первое подозрение было в том, что есть что-то не так, когда я назначаю data->message = message
, поэтому я попытался назначить строку непосредственно data->message
, но не повезло. Но я все еще думаю, что ошибка должна быть там, поскольку исключение составляет std::length_error
, брошенное «basic_string».
Или, может быть, когда я перехожу data
в pthread_create
или когда я делаю бросок по строке 18, я сделал что-то не так. Моя мысль заключается в том, что когда я передаю ее функции, я передаю ее в виде указателя, отбросив ее до указателя void void *
. Когда printHello
получил этот параметр, я произвел его на тип thread_data*
, который является указателем, который является тем, чем он был первоначально.
Вот тогда я могу придумать до сих пор. Прошу прокомментировать, если что-то неясное в моем письме (английский не мой первый язык).
Спасибо всем заблаговременно.
Спасибо, в этом была проблема. Я присоединился к потоку перед вызовом delete, и он работал нормально. –
@QuanTran: обратите внимание, что если вы присоединитесь к потоку внутри цикла for, вы не будете запускать свои потоки параллельно. Вы захотите присоединиться к потокам * после * цикла for (что также означает, что вам нужно будет отслеживать указатели данных за пределами цикла for). –
Спасибо, я этого не замечал до сих пор.Я на самом деле изучил параллелизм в Java, написав диспетчер загрузки, но поскольку этот проект больше этого небольшого упражнения, я создал потоки и присоединил их к различным циклам, в то время как для этого небольшого упражнения я просто помещал их все в один цикл. Большое спасибо :) –