未定义行为(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,因为在操作之间没有序列点(sequence points)来修改和读取变量a。标准未保证确定的结果,编译器可能得到任何结果或甚至生成意外的代码。
故事 在一个数据存储系统的项目中,一位开发者在低级函数中出现了数组越界错误。UB仅在特定的用户数据上表现出来,导致文件结构损坏和客户数据丢失。
故事 在微控制器项目中,出现了读取未初始化变量的结构。测试通过了,但在设备发布一年后发现了随机错误,这是由于UB引起的:变量有时包含垃圾值。
故事 在一个大型开源项目中,发现一个描述符在不同代码部分被释放两次。这种UB起初表现得非常少见,但在新版本的操作系统中导致了频繁的崩溃。