C 未定义行为(Undefined Behavior, UB)
未定义行为指标准未规定结果的操作,编译器可做任意处理,后果不可预测。理解并避免 UB 对可靠与安全的 C 程序至关重要。
1. 常见 UB 列表
- 访问越界(数组/指针算术越界,含尾后位置解引用)。
- 使用未初始化变量的值。
- 解引用空指针或悬空指针,二次 free。
- 有符号整数溢出(如
INT_MAX + 1)。 - 移位位数无效(如对 32 位整型左移 ≥32)。
- 违反严格别名(strict aliasing):通过不兼容类型指针访问同一对象。
- 修改字符串字面量内容。
- 在一个序列点之间对同一对象多次非序列化修改并读取(如
i = i++ + ++i;)。
2. 严格别名与规避
- 通过不同类型指针访问同一内存会触发 UB,例外:
char*/unsigned char*可查看任意对象的字节表示。 - 规避:
- 使用
memcpy在不同类型对象间转移字节表示。 - 使用
union(仍需谨慎,跨平台可移植性有限)。
- 使用
3. 生命周期与对齐
- 访问已结束生命周期的对象是 UB。
- 未对齐的指针解引用在某些架构下是 UB。
4. 实践建议
- 打开编译器告警并使用静态分析。
- 编写单元测试覆盖边界情况。
- 避免依赖实现细节,遵循标准规则。
- 对外部输入做严格校验与范围检查。
5. 小结
UB 不是“偶尔错”,而是“任何结果都有可能”。从源头设计与代码风格上规避 UB,是 C 工程质量的基石。