Analyzability
这种对 C 语言的可选扩展限制了执行某些形式的未定义行为的潜在结果,这提高了此类程序的静态分析的有效性。如果预定义的宏常量__STDC_ANALYZABLE__
(C11)由编译器定义,则只能保证可分析性。
如果编译器支持可分析性,那么其行为未定义的任何语言或库构造会进一步分类为关键和有界的未定义行为,并且所有有界 UB 情况的行为都受到限制,如下所述。
严重未定义的行为
严重的 UB 是未定义的行为,可能会执行内存写入或读取任何对象边界的易失性内存。具有严重未定义行为的程序可能容易受到安全漏洞攻击。
只有以下未定义的行为至关重要:
- 访问其生命周期之外的对象(例如,通过悬挂指针)
- 写入声明不兼容的对象打算
- 函数通过一个函数指针调用,该指针的类型与它指向的函数的类型不兼容
- 评估左值表达式,但不指定对象
- 尝试修改字符串文字
- 解引用无效(空,不确定等)或过去结束指针
- 通过非const指针修改const对象
- 使用无效参数调用标准库函数或宏
- 使用意外的参数类型调用可变参数标准库函数(例如,
printf
使用与其转换说明符不匹配的参数调用) longjmp
没有setjmp
调用范围,跨线程或VM类型的范围内。- 任何使用由
free
or 释放的指针realloc
- 任何字符串或宽字符串库函数都会访问数组越界
界定未定义的行为
有界 UB 是未定义的行为,不能执行非法的内存写入,尽管它可能会陷入并可能产生或存储不确定的值。
- 所有未定义的行为都未被列为关键性的,包括
- 多线程数据竞赛
- 使用具有自动存储持续时间的不确定值
- 严格的走样违规
- 错位的对象访问
- 有符号整数溢出
- 无序的副作用修改相同的标量或修改并读取相同的标量
- 浮点到整数或指针到整数的转换溢出
- 按位移动一个负数或太多的位数
- 整数除以零
- 使用void表达式
- 直接分配或
memcpy
不精确重叠的对象 - 限制违规
- 所有未定义的行为都不在关键列表中。
注意
有界的未定义行为会禁用某些优化:启用可分析性的编译会保留源代码因果关系,否则可能会违反未定义的行为。
分析性扩展允许在发生陷阱时调用运行时约束处理程序,作为实现定义的行为的一种形式。
参考
- C11标准(ISO / IEC 9899:2011):
- 6.10.8.3/1条件特征宏(p:177)
- 附件L可分析性(p:652-653)
本文档系腾讯云开发者社区成员共同维护,如有问题请联系 cloudcommunity@tencent.com