Запуск вашей программы под valgrind
подтверждает ваш диагноз, что проблема возникает, когда вы звоните pthread_join
.Это также можно определить, запустив его в отладчике, но Valgrind часто особенно полезен для segfaults, потому что анализ использования памяти часто помогает также определить причину проблемы.
В этом случае, однако,основная проблема ясна: вы вызываете pthread_join()
с неверным первым аргументом.Похоже, у вас есть некоторое недопонимание:
Насколько я понимаю, цикл for должен быть таким же, как цикл для pthread_create()
Нет,не обязательно.Единственная существенная связь с pthread_create
состоит в том, что первый аргумент, идентификатор потока, должен быть значением, которое было сохранено pthread_create()
, идентифицируя поток, который не был ни отсоединен, ни уже не присоединен.Может быть целесообразно выполнять объединения в цикле , аналогичном , в котором вы запускаете потоки, но это зависит от конкретных требований вашего приложения.Однако, как правило, эти требования включают в себя то, что все рабочие потоки завершаются до того, как основной поток проходит какую-то точку, и для достижения этого каждый из них должен быть объединен.
и переменная, переданная вэто разыменованный указатель, передаваемый в функцию pthread_exit ().
Зная, как я делаю поведение pthread_join()
, я могу просто сжать эти слова в форму, которая подходит.Я бы сказал что-то вроде: «Второй аргумент, если он не нулевой, это указатель на местоположение, в которое нужно записать возвращаемое значение функции потока или значение, переданное ей pthread_exit()
».
В любом случае, основная проблема заключается в том, что я уже высказал в комментариях: в цикле соединения вы перезаписываете идентификаторы потоков, предоставленные pthread_create
, и передаете произвольные значения в pthread_join
. Они не идентифицируют ваши потоки , и в случае, если ваша реализация pthreads похожа на мою, неверные идентификаторы потоков в действительности становятся недействительными указателями.То, что вы, похоже, не оценили, это то, что pthread_create
генерирует и назначает идентификаторы потоков.Вот почему вы должны передать ему адрес, по которому нужно хранить идентификатор.Как следствие, бесполезно инициализировать переменную ID потока перед передачей ее адреса в pthread_create
.
Очистка этой проблемы и повторный запуск вашей программы под valgrind показывает, что у вас есть дополнительная проблемав вашей функции потока, как также указано в другом ответе.Это происходит отчасти потому, что ваш четвертый аргумент pthread_create
не соответствует использованию вашего аргумента вашей потоковой функцией.
Четвертый аргумент pthread_create
напрямую передается в функцию потока.Вы передаете &argv[i]
, который является адресом char *
, он же char **
, автоматически преобразуется в void *
.Ваша функция потока передает свой аргумент непосредственно в atoi()
, с автоматическим преобразованием в тип char *
.Обратите внимание, что char *
! = char **
.Я думаю, вы хотите, чтобы четвертый аргумент pthread_create
был просто argv[i]
.По крайней мере, этот тип соответствует вашему использованию.
Сделав эту коррекцию, я также обнаружил, что ваша программа оказывается в бесконечном цикле внутри вашего цикла pthread_join
.Я не уверен, почему вы там зацикливаетесь - это кажется совершенно бесполезным.