可视化 C++编译器如何设法发出完全无意义的代码
visual How does a C++ compiler manage to emit completely pointless code?
这是这个问题中代码的略微修改版本:
#pragma warning(default:4716)
int recur(int i)
{
int result;
result = (i>1 ? i - recur(i/2) : 3);
// return intentionally omitted
}
int main()
{
return recur(0);
}
请注意,recur()
省略了return
,因此其行为是未定义的。下面是 Visual C++ 10 为此代码发出的内容:
316: int main()
317: {
00403940 push ecx
318: return recur(0);
00403941 mov eax,dword ptr [esp]
319: }
00403944 pop ecx
00403945 ret
是的,我知道在未定义的行为的情况下,任何事情都是允许的。但是这段代码是完全没有意义的,编译器就是一个程序,所以我不会期望它有毫无意义的东西。
编译器如何设法发出完全无意义的代码?
从编译器的角度来看return smth;
语句意味着简单的事情:生成一些代码以根据调用约定将结果返回给调用者(这是针对"C",x86/amd64和琐碎类型通常意味着将smth放入eax
/rax
寄存器)。 如果您错过了return
这只是意味着编译器不会生成此类代码(mov result, %eax
)。 通常它会导致警告(至少): 返回非 void 的函数中没有返回语句。但如果函数体有 asm
个部分来代替编译器来做这件事,那可能是完全可以的......在那种(罕见)情况下,警告通常由 #pragma 或相应的命令行选项抑制。是的,一般来说,错过退货会导致 UB...
由于代码具有未定义的行为,编译器实际上可以做任何事情,包括生成毫无意义的代码。
这里最有可能发生的事情是编译器忠实地编译了您的代码并将其传递给优化器,优化器执行了一些内联和常量表达式折叠。
在损坏的代码上使用该过程恰好导致了您所看到的结果。
相关文章:
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 代码在main()中运行,但在函数中出现错误
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 编译包含字符串的代码时遇到问题
- 我在c++代码中生成了一个运行时#3异常
- 如何在linux终端中同时编译和运行c++代码
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 在Linux for Windows上编译C++代码时出错
- 我的字符计数代码计算错误.为什么
- 孤立代码块在结构中引发异常
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 此代码是否违反一个定义规则
- 为什么我的代码在输出中增加了93天
- 我的简单if-else语句是如何无法访问的代码
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 代码打印出一系列无意义的数字
- 代码将无意义输出到输出文件而不是字符串
- 可视化 C++编译器如何设法发出完全无意义的代码