1
36
程序包含未定义的行为,如取消引用空指针
(即呼叫
正在执行
此版本生成的代码如下所示:
它尝试调用
现在,让我们检查同一个程序,但在以下方面进行优化:
此版本生成的代码如下所示:
有趣的是,不知何故,优化修改了程序
让我们回到标准(特别是N4660)上来。什么 它说的是未定义的行为吗?
强调我的。
表现出未定义行为的程序变得无用,因为一切
到目前为止,它已经做了,并且将进一步做,如果它包含
错误的数据或构造。记住这一点,一定要记住
编译器可能会完全忽略未定义行为的情况
被命中,这实际上是在优化
程序例如
笔记 :无符号整数不能进行相同的优化,因为溢出整数不是UB。也就是说,编译器需要保持表达式的原样,因为当发生溢出时,它可能有不同的求值(无符号是模块2 N ,其中N是位数)。为无符号整数优化它将不符合标准(感谢aschepler)。
这很有用,因为它允许
tons of optimizations to kick
in
. 所以
很好,但如果
现在我们有足够的信息,以便更好地检查您的故障 程序我们已经知道访问空指针是未定义的 行为,这就是导致运行时出现有趣行为的原因。 所以,让我们试着理解为什么Clang(或技术上的LLVM)优化了 程序的运行方式。
记住你可以打电话
如果在程序中编写此代码段,则程序编号 较长时间显示未定义的行为 “硬格式 磁盘驱动器!" 显示,并启用或禁用优化。
那么这个程序有效的唯一方法是什么?有这个
很酷,但没人打电话
例如,当
constant
folding
是
应用时,它会看到
Dead code elimination
和
interprocedural optimization
可能会发现如果
Inline expansion
优化
看到了吗
这在某种程度上相当于启用优化的Clang的输出。当然,Clang真正做的可能(也可能)有所不同,但优化仍然能够得出相同的结论。 在对GCC的输出进行优化的情况下进行检查,似乎并不费心调查:
执行该程序会导致崩溃(分段错误),但如果调用
随着越来越多的优化被设计出来,所有这些都会发生疯狂的变化,因此不要相信编译器会处理包含未定义行为的代码,这也可能会把你搞砸(并真正格式化你的硬盘!) 我建议你阅读 What every C programmer should know about Undefined Behavior 和 A Guide to Undefined Behavior in C and C++ ,这两个系列文章都提供了丰富的信息,可能会帮助您了解最先进的技术。 |
2
0
除非实现指定尝试调用空函数指针的效果,否则它可能会表现为对任意代码的调用。这种任意代码的行为完全可以像调用函数“foo()”一样。虽然C标准的附录L要求实现区分“关键UB”和“非关键UB”,并且一些C++实现可能会应用类似的区分,但在任何情况下调用无效的函数指针都是关键UB。 请注意,这个问题中的情况与例如。
在后一种情况下,当执行达到
|
rookie · 检查函数模板的所有参数包参数是否属于int 1 年前 |
ivaigult · -W转换和隐式字符串到布尔类型转换 1 年前 |
rainer · 后台插入程序的初始化 1 年前 |
Community wiki · 以理智、安全和高效的方式复制文件 1 年前 |
Shefali Kanaujia · 对C中向量的向量进行排序++ 1 年前 |
Ma Joonyoung · 粗粒度和细粒度链表的时间比较 1 年前 |