exponenta event banner

Правило AUTOSAR C++ 14 A15-4-3

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

Описание

Определение правила

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

Объяснение

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

Чтобы избежать неопределенного поведения и уязвимостей безопасности:

  • Сохранить одну и ту же спецификацию исключения во всех объявлениях функции.

  • Если виртуальная функция объявлена с помощью noexcept или noexcept(true) в качестве спецификации исключения объявите функции переопределителя в производных классах, используя ту же спецификацию.

  • Если виртуальная функция объявлена с помощью noexcept(false) в качестве спецификации исключения объявите функции-переопределители в производных классах, используя либо noexcept(false) или noexcept(true) в качестве спецификации исключения.

Внедрение Polyspace

Polyspace ® помечает спецификацию исключения функции, если функция объявлена с различными спецификациями исключения в разных местах файла. Polyspace помечает функцию-переопределитель в производном классе, если она указана какnoexcept(fale) в то время как виртуальная функция в базовом классе указана как noexcept.

Поиск неисправностей

Если вы ожидаете нарушения правила, но не видите его, обратитесь к разделу Нарушения стандартов кодирования не отображаются.

Примеры

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

В этом примере показано, как Polyspace помечает объявления одной функции, имеющей различные спецификации исключений. В одном файле file1.cpp, функции-члены классов A и B объявлены.

//file1.cpp
class A
{
public:
	void F() noexcept;
	void G() noexcept(false);
	
};
class B
{
public:
	void W() noexcept;
	void R() noexcept(false);
	
};

В другом файле file2.cpp, определяются функции-члены этих классов.

// file2.cpp
#include"file1.cpp"

void A::F() noexcept(false) //Noncompliant
{
	// Implementation
}
void A::G() noexcept //Noncompliant
{
	// Implementation
}


void B::W() noexcept //Compliant
{
	// Implementation
}
void B::R() noexcept(false) //Compliant
{
	// Implementation
}

Чтобы увидеть нарушения этого правила, запустите Polyspace и укажите оба file1.cpp и file2.cpp в качестве исходных файлов с помощью опции -sources. Держать file1.cpp и file2.cpp в той же папке. Посмотрите -sources дополнительные сведения об указании нескольких исходных файлов.

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

  • Функция A::F() объявлен вfile1.cpp с помощью спецификации исключений noexcept, но он объявляется с помощью спецификации исключения noexcept(false) в file2.cpp. Polyspace помечает неидентичную спецификацию исключения в последнем объявлении. По той же причине спецификация исключения A::G() в file2.cpp также помечен.

  • Функции B::W() и B::R() объявляются и определяются с помощью одной и той же спецификации исключения в двух исходных файлах. Эти функции соответствуют этому правилу.

В этом примере показано, как Polyspace помечает объявление функций-переопределителей с менее строгими спецификациями исключений.

class A
{
public:
	virtual void V1() noexcept = 0;
	virtual void V2() noexcept(false) = 0;
	virtual void V3() noexcept = 0;
};
class B : public A
{
public:
	void V1() noexcept(false) override //Noncompliant
	{
		// Implementation
	}
	void V2() noexcept override //Compliant
	{
		// Implementation
	}
	void V3() noexcept override //Compliant
	{
		// Implementation
	}
};

Чистые виртуальные функции A::V1(), A::V2(), и A::V3() реализуются переопределяющими функциями B::V1(), B::V2(), и B::V3() соответственно.

  • Polyspace помечает функцию B::V1() поскольку эта переопределяющая функция задается с использованием менее ограничительной спецификации исключения noexcept(false) по сравнению с виртуальной функцией базового класса A::V1(), которая определяется с помощью noexcept.

  • Polyspace не помечен B::V2() поскольку эта переопределяющая функция задается с помощью более ограничительной спецификации noexcept по сравнению с виртуальной функцией базового класса A::V2(), которая определяется с помощью noexcept(false).

  • Polyspace не помечен B::V3() поскольку эта переопределяющая функция задается с использованием той же спецификации исключения, что и виртуальная функция базового класса A::V3().

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

Группа: Обработка особых ситуаций
Категория: Обязательно, Автоматизировано
Представлен в R2020b