命名空间
变体
操作

可分析性

来自 cppreference.com
< c‎ | 语言

此 C 语言可选扩展限制了执行某些形式的未定义行为的潜在结果,从而提高了对此类程序的静态分析的有效性。只有当编译器定义了 预定义宏常量 __STDC_ANALYZABLE__(C11) 时,才保证启用可分析性。

如果编译器支持可分析性,则任何其行为未定义的语言或库结构将进一步分类为 *关键* 未定义行为和 *有界* 未定义行为,并且所有有界 UB 情况的行为都将按如下所述限制。

内容

[编辑] 关键未定义行为

关键 UB 是可能对任何对象的边界之外进行内存写入或易失性内存读取的未定义行为。具有关键未定义行为的程序可能容易受到安全漏洞的攻击。

只有以下未定义行为是关键的

  • 访问其 生命周期 外部的对象(例如,通过悬空指针)
  • 写入其声明与之不 兼容 的对象
  • 通过类型与指向的函数类型不 兼容 的函数指针调用函数
  • 左值表达式 进行求值,但它不指定对象
  • 尝试修改 字符串字面量
  • 对无效(空、不确定等)或 越界 指针进行 解引用
  • 通过非 const 指针修改 const 对象
  • 调用标准库函数或宏,并使用无效的参数
  • 使用意外的参数类型调用可变参数标准库函数(例如,使用与转换说明符不匹配的类型的参数调用 printf
  • 在没有 setjmp 的调用范围、跨线程或 VM 类型范围内使用 longjmp
  • 使用由 freerealloc 释放的指针
  • 任何 字符串宽字符串 库函数访问越界的数组

[编辑] 有界未定义行为

有界 UB 是不能执行非法内存写入的未定义行为,尽管它可能会陷入陷阱,并可能产生或存储不确定的值。

  • 所有未列为关键的未定义行为都是有界的,包括
  • 多线程数据竞争
  • 使用具有自动存储持续时间的 不确定值
  • 严格别名 违规
  • 未对齐 的对象进行访问
  • 带符号整数溢出
  • 无序副作用 修改同一个标量或修改和读取同一个标量
  • 浮点数到整数或指针到整数的 转换 溢出
  • 按负数或过大的位数进行 按位移位
  • 对零进行 整数除法
  • 使用空表达式
  • 对不完全重叠的对象进行直接 赋值memcpy
  • restrict 违规
  • 等等。所有不在关键列表中的未定义行为。

[编辑] 备注

有界未定义行为会禁用某些优化:启用可分析性的编译会保留源代码因果关系,而未定义行为可能会 违反 它。

可分析性扩展允许作为一种实现定义的行为,当发生陷阱时,调用 运行时约束处理程序

[编辑] 参考文献

  • C11 标准(ISO/IEC 9899:2011)
  • 6.10.8.3/1 条件特征宏(第 177 页)
  • 附录 L 可分析性(第 652-653 页)