CERT C: Rule CON39-C

Не соединяйте или отсоединяйте поток, к которому ранее соединили или отсоединили

Описание

Управляйте определением

Не выполняйте операции, которые могут блокироваться при содержании lock.[1]

Реализация Polyspace

Это средство проверки проверяет на Соединение или отсоединение к которому соединяют или отдельного потока.

Примеры

развернуть все

Проблема

Соединение или отсоединение к которому соединяют или отдельного потока происходят когда:

  • К потоку, к которому соединяют, ранее соединили или отсоединили

  • К потоку, который отсоединяется, ранее соединили или отсоединили.

Панель 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;    
}

Проверяйте информацию

Группа: правило 14. Параллелизм (CON)
Введенный в R2019b

[1]  Это программное обеспечение было создано MathWorks, включающим фрагменты: “Веб-сайт SEI CERT-C”, © 2017 Carnegie Mellon University, веб-сайт SEI CERT-C © 2017 Carnegie Mellon University”, CERT SEI C Кодирование Стандарта – Правил для Разработки безопасных, Надежных и Защищенных систем – 2 016 Выпусков”, © 2016 Carnegie Mellon University, and “CERT SEI Стандарт Кодирования C++ – Правил для Разработки безопасных, Надежных и Защищенных систем на C++ – 2 016 Выпусков” © 2016 Carnegie Mellon University, со специальным разрешением от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ-МЕЛЛОН И/ИЛИ ЕГО ИНСТИТУТА ПРОГРАММНОЙ ИНЖЕНЕРИИ СОДЕРЖАЛ, ЗДЕСЬ ПРЕДОСТАВЛЯЕТСЯ НА БАЗИСЕ "ASIS". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ОПИСАЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

Это программное обеспечение и сопоставленная документация не были рассмотрены, ни являются подтвержденным Университетом Карнеги-Меллон или его Институтом программной инженерии.