可视化 C++编译器如何设法发出完全无意义的代码

visual How does a C++ compiler manage to emit completely pointless code?

本文关键字:无意义 代码 编译器 C++ 可视化      更新时间:2023-10-16

这是这个问题中代码的略微修改版本:

#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...

由于代码具有未定义的行为,编译器实际上可以做任何事情,包括生成毫无意义的代码。

这里最有可能发生的事情是编译器忠实地编译了您的代码并将其传递给优化器,优化器执行了一些内联和常量表达式折叠。
在损坏的代码上使用该过程恰好导致了您所看到的结果。