ПроблемаСоединение или отсоединение к которому соединяют или отдельного потока происходят когда:
К потоку, к которому соединяют, ранее соединили или отсоединили
К потоку, который отсоединяется, ранее соединили или отсоединили.
Панель Result Details описывает, соединили ли к потоку ранее или отсоединили и также показывает предыдущие связанные события.
Например, проблема происходит когда поток, к которому соединяют с thrd_join
затем отсоединяется с pthread_detach
:
thrd_t id;
//...
thrd_join(id, NULL);
thrd_detach(id);
Обратите внимание на то, что поток рассматривается, как соединено, только если присоединение предыдущего сообщения успешно. Например, поток не рассматривается, как присоединяется if
перейдите здесь:
thrd_t t;
//...
if (thrd_success != thrd_join(t, 0)) {
/* Thread not considered joined */
}
Анализ не может обнаружить случаи, где поток, к которому соединяют, отсоединяет себя использование, например,
thrd_current()
функция.
РискСтандарт C11 (пункты 7.26.5.3 и 7.26.5.6) утверждает, что к потоку нельзя соединить или отсоединить, если к этому ранее соединили или отсоединили. Нарушение этих пунктов стандарта приводит к неопределенному поведению.
ФиксацияПостарайтесь не соединять поток, к которому уже соединили или отсоединился ранее. Аналогично, постарайтесь не отсоединять поток, к которому уже соединили или отсоединили.
Пример – присоединение вместе с путем отсоединения потока
#include <stddef.h>
#include <threads.h>
#include <stdlib.h>
extern int thread_func(void *arg);
int main (void)
{
thrd_t t;
if (thrd_success != thrd_create (&t, thread_func, NULL)) {
/* Handle error */
return 0;
}
if (thrd_success != thrd_join (t, 0)) {
/* Handle error */
return 0;
}
if (thrd_success != thrd_detach (t)) {
/* Handle error */
return 0;
}
return 0;
}
В этом примере, использовании thrd_detach
на потоке, к которому ранее соединили с thrd_join
приводит к неопределенному поведению.
Чтобы избежать ошибок компиляции с этим примером, задайте стандарт C11 с опцией C standard version (-c-version)
.
Коррекция – старается не отсоединять поток, к которому соединяют,Удалите thrd_join
или thrd_detach
оператор.
#include <stddef.h>
#include <threads.h>
#include <stdlib.h>
extern int thread_func(void *arg);
int main (void)
{
thrd_t t;
if (thrd_success != thrd_create (&t, thread_func, NULL)) {
/* Handle error */
return 0;
}
if (thrd_success != thrd_join (t, 0)) {
/* Handle error */
return 0;
}
return 0;
}
Пример – соединяющий поток, созданный в отдельном состоянии#include <stddef.h>
#include <pthread.h>
#define thread_success 0
extern void *thread_func(void *arg);
int main() {
pthread_t id;
pthread_attr_t attr;
if(thread_success != pthread_attr_init(&attr)) {
return 0;
}
if(thread_success != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
return 0;
}
if(thread_success != pthread_create(&id, &attr, thread_func, NULL)) {
return 0;
}
if(thread_success != pthread_join(id, NULL)) {
return 0;
}
return 0;
}
В этом примере атрибут потока присвоен PTHREAD_CREATE_DETACHED
состояния
. К созданному использованию потока этого атрибута затем соединяют.
Коррекция – создает потоки как JoinableОдна возможная коррекция должна создать поток с атрибутом потока, присвоенным PTHREAD_CREATE_JOINABLE
состояния
и затем соедините поток.
#include <stddef.h>
#include <pthread.h>
#define thread_success 0
extern void *thread_func(void *arg);
int main() {
pthread_t id;
pthread_attr_t attr;
if(thread_success != pthread_attr_init(&attr)) {
return 0;
}
if(thread_success != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)) {
return 0;
}
if(thread_success != pthread_create(&id, &attr, thread_func, NULL)) {
return 0;
}
if(thread_success != pthread_join(id, NULL)) {
return 0;
}
return 0;
}