V2614. MISRA. External identifiers should be distinct.
Данное диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Это правило актуально только для С. Идентификаторы с внешним типом связывания должны быть различимы в пределах ограничений, накладываемых используемым стандартом.
Ограничения:
- до стандарта С99 – 6 значимых символов, не учитывая регистр;
- начиная со стандарта С99 – 31 значимый символ, учитывая регистр.
Рассмотрим первый пример:
// 123456789012345678901234567890123
extern int shrtfn(void); // OK
extern int longfuncname(void); // Error in С90,
// but ОК in С99
extern int longlonglonglonglongfunctionname1(void); // Error in both
Длинные идентификаторы затрудняют чтение кода, а также могут быть перепутаны с автоматически сгенерированными. Также, в случае если два идентификатора различаются только в незначащих символах, то поведение не определено.
На практике некоторые имплементации (компиляторов и компоновщиков) могут иметь собственные ограничения. Для их уточнения стоит обратиться к документации.
Рассмотрим второй пример:
// 123456789012345678901234567890123
extern int longFuncName1(int);
extern int longFuncName2(int);
extern int AAA;
extern int aaa;
void foo(void)
{
longFuncName2(AAA);
}
В данном коде присутствует сразу несколько ошибок (рассмотрим на примере стандарта C90):
- Идентификаторы 'longFuncName1' и 'longFuncName2' будут сокращены до 6 первых символов ('longFu') и станут одинаковыми с точки зрения компоновщика.
- Согласно стандарту С90, идентификаторы не всегда являются регистрозависимыми, а поэтому идентификаторы 'AAA' и 'aaa' также могут стать одинаковыми для линковщика.
- В функции 'foo' происходит вызов функции 'longFuncName2', в которую передаётся значение переменной 'AAA'. Проблема здесь в том, что оба эти идентификатора не являются однозначными, а потому этот вызов приведёт к неопределённому поведению.
Данная диагностика классифицируется как:
|