AUTOSAR C++14 Rule 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