exponenta event banner

Отсутствует блокировка

Функция разблокировки без функции блокировки

Описание

Этот дефект возникает, когда задача вызывает функцию разблокировки перед вызовом соответствующей функции блокировки.

В многозадачном коде функция блокировки начинает критический раздел кода и функция разблокировки заканчивает его. Когда задача my_task вызывает функцию блокировки my_lock, другие задачи, вызывающие my_lock должен подождать до my_task вызывает соответствующую функцию разблокировки. Polyspace ® требует, чтобы функции блокировки и разблокировки имели формуvoid func(void).

Чтобы найти этот дефект, перед анализом необходимо указать параметры многозадачности. Чтобы задать эти параметры, на панели Конфигурация выберите Многозадачность.

Риск

Вызов функции разблокировки без соответствующей функции блокировки может указывать на ошибку кодирования. Например, возможно, функция разблокировки не соответствует функции блокировки, которая начинает критическую секцию.

Зафиксировать

Исправление зависит от первопричины дефекта. Например, если дефект возникает из-за несоответствия между функцией блокировки и функцией разблокировки, проверьте пару функция блокировки-разблокировки в конфигурации анализа Polyspace и исправьте несоответствие.

См. примеры исправлений ниже. Чтобы избежать проблемы, можно следовать практике вызова функций блокировки и разблокировки в одном модуле на одном уровне абстракции. Например, в этом примере func вызывает функцию блокировки и разблокировки на одном уровне, но func2 не делает.

void func() {
  my_lock();
  {
    ...
  }
  my_unlock();
}

void func2() {
  {
   my_lock();
   ...
  }
  my_unlock();
}

Если вы не хотите устранять проблему, добавьте комментарии к результату или коду, чтобы избежать другой проверки. См. раздел Результаты анализа пространства адресов с помощью исправлений ошибок или обоснований.

Примеры

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



void begin_critical_section(void);
void end_critical_section(void);

int global_var;

void reset(void) 
{
  begin_critical_section();
  global_var = 0;
  end_critical_section();
}

void my_task(void)
{
  global_var += 1;
  end_critical_section();
}

В этом примере для эмуляции многозадачности необходимо указать следующие параметры.

ВыборСпецификация
Configure multitasking manually
Tasks (-entry-points)

my_task, reset

Critical section details (-critical-section-begin -critical-section-end)Запуск подпрограммыЗавершение процедуры
begin_critical_sectionend_critical_section

В командной строке можно использовать следующее:

polyspace-bug-finder
   -entry-points my_task,reset
   -critical-section-begin begin_critical_section:cs1
   -critical-section-end end_critical_section:cs1

Пример имеет две точки входа, my_task и reset. my_task требования end_critical_section перед вызовом begin_critical_section.

Исправление - обеспечить блокировку

Одной из возможных корректировок является вызов функции блокировки. begin_critical_section перед инструкциями в критическом разделе.



void begin_critical_section(void);
void end_critical_section(void);

int global_var;

void reset(void) 
{
  begin_critical_section();
  global_var = 0;
  end_critical_section();
}

void my_task(void)
{
    begin_critical_section();
    global_var += 1;
    end_critical_section();
}


void begin_critical_section(void);
void end_critical_section(void);

int global_var;

void reset() {
    begin_critical_section();
    global_var=0;
    end_critical_section();
}

void my_task(void) {
    int index=0;
    volatile int numCycles;
    
    while(numCycles) {
      if(index%10==0) {
        begin_critical_section();
        global_var ++;  
      }
      end_critical_section(); 
      index++;
    }
}

В этом примере для эмуляции многозадачности необходимо указать следующие параметры.

ВыборСпецификация
Configure multitasking manually
Tasks (-entry-points)

my_task, reset

Critical section details (-critical-section-begin -critical-section-end)Запуск подпрограммыЗавершение процедуры
begin_critical_sectionend_critical_section

В командной строке можно использовать следующее:

polyspace-bug-finder
   -entry-points my_task,reset
   -critical-section-begin begin_critical_section:cs1
   -critical-section-end end_critical_section:cs1

Пример имеет две точки входа, my_task и reset.

В while петля, my_task оставляет критический участок через вызов end_critical_section();. В итерации while цикл:

  • Если my_task входит в if состояние ветвь, критический раздел начинается через вызов begin_critical_section.

  • Если my_task не вводит if состояние ветвь и покидает while цикл, критический раздел не начинается. Поэтому возникает дефект отсутствующей блокировки.

  • Если my_task не вводит if ветвь условия и переходит к следующей итерации while шлейф, функция разблокировки end_critical_section вызывается снова. Возникает дефект двойной разблокировки.

Поскольку numCycles является volatile переменная, она может принимать любое значение. Возможны любые из вышеуказанных случаев. Поэтому при вызове появляются дефект отсутствующей блокировки и дефект двойной разблокировки end_critical_section.

Информация о результатах

Группа: Параллелизм
Язык: C | C++
По умолчанию: Вкл.
Синтаксис командной строки: BAD_UNLOCK
Воздействие: среднее
CWE ID: 832
Представлен в R2014b