exponenta event banner

Правило AUTOSAR C++ 14 A18-5-2

Использование новых или удаленных выражений при неразмещении не допускается

Описание

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

Использование новых или удаляемых выражений без размещения не допускается.

Объяснение

new оператор выделяет память. delete оператор освобождает память. При явном использовании этих операторов их необходимо соединить, чтобы избежать утечки памяти. Даже в этом случае неожиданные исключения или возврат могут привести к утечке памяти. Рассмотрим этот код, в котором память выделяется указателю явным вызовом new и освобожден явным вызовом delete.

std::int32_t ThrowError(){
	std::int32_t errorCode;
	std::int31_t* ptr = new std::int32_t{0};
	//...
	if(errorCode!=0){
		throw std::runtime_error{"Error"};
	}
	//...
	if (errorCode != -1) {
		return 1;  
	}
	delete ptr;  
	return errorCode;
}
Даже несмотря на new оператор связан с delete оператор, этот код может привести к утечке памяти в определенных условиях.

  • Если первый if() оператор - true, то функция создает исключение и выходит без удаления указателя.

  • Если второй if() оператор - true, то функция возвращает 1 и выходит без удаления указателя.

Чтобы избежать непредсказуемой утечки памяти, инкапсулируйте в объекты ресурсы, такие как динамически выделяемая память или дескрипторы файлов. Получение ресурсов в конструкторах объектов и освобождение ресурсов в деструкторах объектов. Этот шаблон конструкции называется «Resource Acquisition Is Initialization» или RAI. Следование шаблону RII предотвращает утечку памяти, даже если есть неожиданные исключения и возврат.

Можно также использовать объекты диспетчера, которые управляют временем жизни динамически выделенных ресурсов. Примеры управляющих объектов в стандартной библиотеке:

  • std::unique_ptr вместе с std::make_unique

  • std::shared_ptr вместе с std::make_shared

  • std::string

  • std::vector

Это правило не применяется к new оператор или delete оператор в определяемых пользователем классах RII и менеджерах.

Внедрение Polyspace

AUTOSAR C++ 14 разрешает явное выделение ресурсов путем вызова new в двух случаях, когда выделенный ресурс немедленно передается:

  • Объект менеджера

  • Класс RAI, который не имеет безопасной альтернативы new оператор.

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

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

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

Примеры

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

Этот код показывает, как флаги Polyspace new или delete операторов.

#include <cstdint>
#include <memory>
#include <vector>
#include <cstddef>

using namespace std;

int32_t Fn1()
{
	int32_t errorCode{0};
	int32_t* ptr =
	new int32_t{0}; //Noncompliant
	// ...
	if (errorCode != 0) {
		throw  runtime_error{"Error"}; // Possible Memory Leak
	}
	// ...
	if (errorCode != 0) {
		return 1; //Possible Memory Leak
	}
	// ...
	delete ptr; //Noncompliant

	return errorCode; // Possible Memory Leak
}

int32_t Fn2()
{
	int32_t errorCode{0};
	// Alternative to 'new'
	unique_ptr<int32_t> ptr1 = make_unique< int32_t>(0); 
	unique_ptr<int32_t> ptr2(new  int32_t{0});   // Noncompliant
	shared_ptr<int32_t> ptr3 =
	make_shared<int32_t>(0);   //Compliant
	vector<int32_t> array;   // Compliant

	if (errorCode != 0) {
		throw  runtime_error{"Error"};   // No memory leaks
	}
	// ...
	if (errorCode != 0) {
		return 1; // No memory leaks
	}
	// ...
	return errorCode; // No memory leaks
}


class X
{
public:
	static void* operator new( size_t s)
	{
		return ::operator new(s);   // Noncompliant
	}

	static void* operator new[]( size_t s)
	{
		return ::operator new(s);   // Noncompliant
	}

	static void operator delete(void* ptr,  size_t s)
	{
		::operator delete(ptr);   // Noncompliant
	}

	static void operator delete[](void* ptr,  size_t s)
	{
		::operator delete(ptr);   // Noncompliant
	}
};

main(){
	X* x1    = new X;   // Noncompliant
	X* x2    = new X[2];   // Noncompliant
}

В Fn1(), операторы new и delete явно вызываются для управления ресурсами. Следовательно, неожиданное исключение или возвращение может привести к утечке памяти. Polyspace помечает new и delete операторов. В Fn2(), объекты менеджера используются для управления памятью. Даже в случаях неожиданных исключений и возвратов утечек памяти в Fn2().

Класс X содержит пользовательские перегрузки для new и delete операторов. Polyspace помечает все экземпляры new и delete в определениях пользовательских перегрузок. В main () Polyspace также помечает перегруженные новые и удаленные операторы.

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

Группа: Библиотека поддержки языка
Категория: Обязательный, частично автоматизированный
Представлен в R2020a