C++ 程序员应该了解哪些常见的未定义行为?
发布于 2022-07-28 22:57:35
C++ 程序员应该了解哪些常见的未定义行为?
说,比如:
a[i] = i++;
关注者
0
被浏览
18
1 个回答
-
指针
- 取消引用
NULL
指针 - 取消引用由大小为零的“新”分配返回的指针
- 使用指向生命周期已结束的对象的指针(例如,堆栈分配的对象或已删除的对象)
- 取消引用尚未明确初始化的指针
- 执行指针运算,产生超出数组边界(上方或下方)的结果。
- 在超出数组末尾的位置取消引用指针。
- 将指针转换为不兼容类型的对象
- 用于
memcpy
复制重叠缓冲区。
缓冲区溢出
- 以负数或超出该对象大小(堆栈/堆溢出)的偏移量读取或写入对象或数组
整数溢出
- 有符号整数溢出
- 评估未在数学上定义的表达式
- 将值左移负数(负数右移由实现定义)
- 将值移动的量大于或等于数字中的位数(例如
int64_t i = 1; i <<= 72
未定义)
类型、类型和常量
- 将数值转换为目标类型无法表示的值(直接或通过 static_cast)
- 在明确分配之前使用自动变量(例如,
int i; i++; cout << i;
) - 使用任何类型的对象的值,而不是
volatile
在sig_atomic_t
接收到信号时 - 尝试在其生命周期内修改字符串文字或任何其他 const 对象
- 在预处理期间将窄字符串与宽字符串文字连接起来
功能和模板
- 不从值返回函数返回值(直接或通过从 try 块流出)
- 同一实体的多个不同定义(类、模板、枚举、内联函数、静态成员函数等)
- 模板实例化中的无限递归
- 使用不同的参数调用函数或链接到函数定义为使用的参数和链接。
面向对象
- 具有静态存储持续时间的对象的级联破坏
- 分配给部分重叠对象的结果
- 在其静态对象的初始化期间递归地重新进入一个函数
- 从对象的构造函数或析构函数对对象的纯虚函数进行虚函数调用
- 引用尚未构造或已销毁的对象的非静态成员
源文件和预处理
- 不以换行符结尾或以反斜杠结尾的非空源文件(C++11 之前)
- 反斜杠后跟不属于字符或字符串常量中指定转义码的字符(这是在 C++11 中实现定义的)。
- 超过实现限制(嵌套块的数量、程序中的函数数量、可用的堆栈空间......)
- 不能用 a 表示的预处理器数值
long int
- 类函数宏定义左侧的预处理指令
#if
在表达式中动态生成定义的标记
待分类
- 在销毁具有静态存储持续时间的程序期间调用 exit
- 取消引用