CERT C++: CON54-CPP

Перенесите функции, которые могут побочно проснуться в цикле

Описание

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

Перенесите функции, которые могут побочно проснуться в loop.[1]

Реализация Polyspace

Это средство проверки проверяет на Функцию, которая может побочно проснуться не перенесенный в цикл.

Примеры

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

Проблема

Функция, которая может побочно проснуться не перенесенный в цикл, происходит, когда следующие функции ожидания при условии вызваны снаружи цикла:

  • C функции:

    • cnd_wait()

    • cnd_timedwait()

  • Функции POSIX:

    • pthread_cond_wait()

    • pthread_cond_timedwait()

  • C++ std::condition_variable и std::condition_variable_any функции члена класса:

    • wait()

    • wait_until()

    • wait_for()

Функции ожидания при условии приостанавливают выполнение вызывающего потока, когда заданное условие соблюдают. Поток просыпается и возобновляется, если другой поток уведомляет его с cnd_broadcast() или эквивалентная функция. Уведомление пробуждения может быть побочным или злонамеренным.

Риск

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

Фиксация

Перенесите функции ожидания при условии, которые могут проснуться побочно в цикле. Цикл проверяет условие пробуждения после возможного побочного уведомления пробуждения.

Пример - std::condition_variable::wait Не перенесенный в цикл
#include <stdio.h>
#include <stddef.h>
#include <thread>
#include <mutex>

#define THRESHOLD 100

std::mutex myMutex;
std::condition_variable cv;

void func(int input)
{
	std::unique_lock<std::mutex> lk(myMutex);
	// test condition to pause thread 
	if (input > THRESHOLD) {
	//pause current thread
		cv.wait(lk);//Noncompliant
	}
}

В этом примере поток использует std::condition_variable::wait приостановить выполнение когда input больше THRESHOLD. Приостановленный поток может возобновиться, использует ли другой поток std::condition_variable::notify_all, который уведомляет все потоки. Это уведомление заставляет поток просыпаться, даже если условие паузы все еще верно.

Коррекция — переносит std::condition_variable::wait в while Циклично выполнитесь явным образом

Одна возможная коррекция должна перенести вызов std::condition_variable::wait в while цикл. Цикл проверяет условие паузы после того, как поток получит возможное побочное уведомление пробуждения.

#include <stdio.h>
#include <stddef.h>
#include <thread>
#include <mutex>

#define THRESHOLD 100

std::mutex myMutex;
std::condition_variable cv;

void func(int input)
{
	std::unique_lock<std::mutex> lk(myMutex);
	// test condition to pause thread 
	while (input > THRESHOLD) {
	//pause current thread
		cv.wait(lk);
	}
}

Коррекция — переносит std::condition_variable::wait в цикле неявно

std::condition_variable::wait функция имеет перегрузку, которая принимает функцию lambda как второй аргумент. Предикат функции Lambda указывает, когда безопасно прекратить ожидать и возобновлять выполнение кода. Эта перегрузка std::condition_variable::wait функция ведет себя, как будто она неявно перенесена в цикл. В этом коде, functionstd::condition_variable::wait вызывается при помощи функции Lambda. Здесь, нежелательное пробуждение потока предотвращено, потому что поток просыпается, когда предикат функции Lambda верен.

#include <stdio.h>
#include <stdio.h>
#include <stddef.h>
#include <thread>
#include <mutex>
#define THRESHOLD 100

std::mutex myMutex;
std::condition_variable cv;

void func(int input)
{
	std::unique_lock<std::mutex> lk(myMutex);
	cv.wait(lk,[&input]{ return !(input>THRESHOLD); });
	
}

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

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

[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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ОПИСАЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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