Неопределённое поведение (Undefined Behavior, 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 (выход за пределы массива) ломал работу всей программы: компилятор удалил не только работу с массивом, но и 'заоптимизировал' часть кода, никак не связанную с ошибкой.