未定义行为(UB)
更新时间:2026-10-01。很多“编译器 bug”其实是程序踩了 UB,编译器只是合法地利用了它。
一、编译器如何利用 UB
编译器假定程序不含 UB 来优化。例如“有符号整数不会溢出”使其可假设循环条件、删除溢出检查分支;“指针必非空”使判空成为死代码。一旦实际发生,行为不可预测且随版本/优化级别变化。
二、高频 UB
数组越界、悬空/野指针、use-after-free、违反严格别名(通过不兼容类型访问)、有符号溢出、读取未初始化变量、重复修改同一对象(序列点)、整数移位越界、漏 return。
三、发现手段

用 ASan/UBSan 定位,不要靠“加个 volatile/降优化”掩盖。
四、常见坑
- 认为 UB 一定崩溃(可能静默错算)。
- 用 gcc 的老行为当标准保证。
- 关掉优化当修复。
小结
总结
未定义行为不是"随机崩溃",而是标准不规定结果、编译器据此假定"程序绝不会踩 UB"做激进优化(假设指针非空、有符号整数不溢出、越界不发生,从而删分支/重排代码),所以"低优化正常、-O2 变样"多半是程序自身踩了越界、悬空指针、严格别名、有符号溢出、未初始化或序列点等高频 UB;正确做法是用 -fsanitize=address/undefined 定位并修复根因,而不是降优化或加 volatile 掩盖。