ПрограммированиеСистемный программист C++

Что такое неопределённое поведение (undefined behavior) в C++? Приведите примеры и расскажите, как его избежать.

Проходите собеседования с ИИ помощником Hintsage

Ответ.

Неопределённое поведение (Undefined Behavior, UB) — это ситуация, при которой стандарт языка не определяет поведение программы. Компилятор может делать с программой что угодно: программа может упасть, дать неверный результат или даже 'работать'. UB возникает из-за ошибок типа выхода за пределы массива, разыменования нулевого указателя и т.д.

Пример эксплицитного UB:

int arr[5]; arr[10] = 42; // UB: выход за границы массива int* p = nullptr; *p = 1; // UB: разыменование 0

Избежать UB можно соблюдением стандартов, использованием современных инструментов (ASan, UBSan, valgrind), стараться не использовать сырые указатели и писать безопасный код.

Вопрос с подвохом.

Если UB случилось в одной части программы, может ли это повлиять на совершенно другую, 'независимую' часть кода?

Да! Компилятор во время оптимизации может сделать неожиданные преобразования, если обнаружено, что возникло UB.

Пример:

void foo(int* p) { if (p == nullptr) return; *p = 5; // А если p был не nullptr, это UB! Но компилятор может удалить проверки, считая, что p всегда валиден. }

Примеры реальных ошибок из-за незнания тонкостей темы.


История

На сервере большой компании из-за разыменования нулевого указателя время от времени происходили рандомные падения процесса, которые сложно было воспроизвести: в debug всё работало, а в релизе — нет.


История

При портировании кода с 32-бит на 64-бит перепутали типы данных, использовали cast между int и указателем. На одних машинах работало, на других появлялись краши и странные артефакты.


История

В интернете известен случай, когда безобидный UB (выход за пределы массива) ломал работу всей программы: компилятор удалил не только работу с массивом, но и 'заоптимизировал' часть кода, никак не связанную с ошибкой.