Анализатор обнаружил non-void функцию, для которой существует путь исполнения, не возвращающий значение. Вызов такой функции ведёт к неопределённому поведению.
Если при исполнении тела non-void функции достигнут конец её тела без 'return', то произойдёт неопределённое поведение.
Рассмотрим пример:
int GetSign(int arg) { if (arg > 0) { return 1; } else if (arg < 0) { return -1; } }
Если в функцию 'GetSign' передать 0, то произойдёт неопределённое поведение. Исправленный вариант:
int GetSign(int arg) { if (arg > 0) { return 1; } else if (arg < 0) { return -1; } return 0; }
Исключением из правила являются функции 'main' и 'wmain'. Для этих функций достижение конца тела эквивалентно выполнению конструкции 'return 0;', поэтому неопределённого поведения не будет. Рассмотрим такой пример:
.... int main() { AnalyzeFile(FILE_NAME); }
В данном случае имеем дело с функцией 'main'. Здесь не будет неопределённого поведения. Соответственно, не будет и выдано предупреждение анализатора. Фрагмент кода эквивалентен следующему:
.... int main() { AnalyzeFile(FILE_NAME); return 0; }
Заметим, что неопределённое поведение происходит, только если конец non-void функции действительно достигнут. В частности, если на пути исполнения тела такой функции произошёл бросок исключения, которое не было перехвачено в теле этой же функции, то неопределённого поведения не будет.
Анализатор не выдаст предупреждение на следующем фрагменте кода:
int Calc(int arg); int Bar(int arg) { if (arg > 0) { return Calc(arg); } throw std::logic_error { "bad arg was passed to Bar" }; }
Также неопределённого поведения не будет, если в ходе выполнения тела такой функции произошел вызов другой функции, которая не возвращает управление. Такие функции обычно помечают '[[noreturn]]'. Поэтому анализатор не выдаст предупреждение на следующем примере:
[[noreturn]] void exit(int exit_code); int Foo() { .... exit(10); }
Данная диагностика классифицируется как:
|
Взгляните на примеры ошибок, обнаруженных с помощью диагностики V591. |