Undefined behavior (UB, неопределённое поведение) — это действия в коде, поведение которых стандарт не определяет. В таких случаях компилятор волен принимать любые решения: программа может работать по-разному на разных платформах, компиляторах, или даже запустить ядерную войну (формально!). Использование UB — самая опасная ошибка в C++.
Примеры UB:
int* p = new int[2]; delete[] p; int x = p[1]; // UB: доступ к памяти после освобождения
Для предотвращения UB:
Что произойдет при следующем коде?
int a = 42; int b = a++ + ++a;Какое значение будет у
b?
Ответ:
Данный код вызывает UB, потому что изменяет и читает переменную a без последовательности точек последовательности (sequence points) между операциями. Стандарт не гарантирует определенного результата, и компилятор может получить любой результат или даже сгенерировать неожиданный код.
История На проекте системы хранения данных один из разработчиков допустил выход за пределы массива в низкоуровневой функции. UB проявлялось только на определённых пользовательских данных и приводило к разрушению структуры файла и потере данных клиентов.
История В проекте для микроконтроллеров встречались конструкции с чтением неинициализированных переменных. Тесты проходили, но спустя год после выхода устройства выявились случайные ошибки в эксплуатации, вызванные UB: переменные иногда содержали мусорные значения.
История В большом open-source проекте был обнаружен дескриптор, освобождаемый дважды из разных частей кода. Это UB сначала проявлялось крайне редко, но в новых версиях ОС стало приводить к частым аварийным остановкам.