V2611. MISRA. Casts between a pointer to an incomplete type and any other type shouldn't be performed.
Данное диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Это правило актуально только для С. Преобразование с использованием указателя на неполный тип может привести к получению неверно выравненного указателя, что может повлечь за собой неопределённое поведение. Такая же ситуация происходит при преобразовании между указателями на неполный тип и числами с плавающей точкой.
Также указатели на неполный тип иногда используются для сокрытия реализации (идиома PIMPL), а приведение к указателю на объект нарушает эту инкапсуляцию.
Рассмотрим пример:
typedef struct _First First;
typedef struct _Second
{
int someVar;
} Second;
void foo(void)
{
First *f;
Second t;
...
f = &t; // <=
...
}
Second* bar(First *ptr)
{
return (Second*)ptr; // <=
}
В приведённом выше коде объявляются структуры 'First' и 'Second'. При этом тип 'First' является не полным, т. к. отсутствует его определение. Далее в функции 'foo' происходит неявное приведение указателя к неполному типу, а в функции 'bar' – явное, но уже из неполного типа в полный. Оба эти случая могут привести к неопределённому поведению.
При этом у правила есть два исключения:
- Константа нулевого указателя ('NULL') может быть приведена к указателю на неполный тип.
- Указатель на неполный тип может быть преобразован в 'void'.
Оба этих случая можно рассмотреть в функции 'baz':
typedef struct _First First;
First* foo(void);
void baz(void)
{
First *f = NULL;
(void)foo();
}
Данная диагностика классифицируется как:
|