任何人都可以解释这个C++代码的内容.它在Linux上编译并执行正常.
#include <iostream>
using namespace std;
int main = ( cout << "Hello world!\n", 195 );
Run Code Online (Sandbox Code Playgroud)
小智 68
数字"195"是x86上RET指令的代码.
C++编译器(在我的情况下是gcc)无法识别"main"未被声明为函数.编译器只看到有"主"符号,并假设它引用了一个函数.
C++代码
int main = ( cout << "Hello world!\n", 195 );
Run Code Online (Sandbox Code Playgroud)
正在初始化文件范围的变量.此初始化代码在C/C++环境调用main()之前执行,但在初始化"cout"变量之后执行.初始化打印"Hello,world!\n",并将变量"main"的值设置为195.完成所有初始化后,C/C++环境调用"main".程序立即从此调用返回,因为我们在"main"的地址处放置了一条RET指令(代码195).
示例GDB输出:
$ gdb ./a
(gdb) break _fini
Breakpoint 1 at 0x8048704
(gdb) print main
$1 = 0
(gdb) disass &main
Dump of assembler code for function main:
0x0804a0b4 <+0>: add %al,(%eax)
0x0804a0b6 <+2>: add %al,(%eax)
End of assembler dump.
(gdb) run
Starting program: /home/atom/a
Hello world!
Breakpoint 1, 0x08048704 in _fini ()
(gdb) print main
$2 = 195
(gdb) disass &main
Dump of assembler code for function main:
0x0804a0b4 <+0>: ret
0x0804a0b5 <+1>: add %al,(%eax)
0x0804a0b7 <+3>: add %al,(%eax)
End of assembler dump.
Run Code Online (Sandbox Code Playgroud)
Ale*_*x B 39
它不是一个有效的C++程序.事实上,在打印"Hello World"之后,它在Mac OSX上崩溃了.
反汇编显示main是一个静态变量,它有初始化器:
global constructors keyed to main:
0000000100000e20 pushq %rbp
0000000100000e21 movq %rsp,%rbp
0000000100000e24 movl $0x0000ffff,%esi
0000000100000e29 movl $0x00000001,%edi
0000000100000e2e leave
0000000100000e2f jmp __static_initialization_and_destruction_0(int, int)
Run Code Online (Sandbox Code Playgroud)
为什么打印"Hello World"?
您看到打印出"Hello World"的原因是因为它在静态初始化main静态整数变量期间运行.在C++运行时甚至尝试调用之前调用静态初始值设定项main().当它发生时,它会崩溃,因为main它不是一个有效的函数,在可执行文件的数据部分只有一个整数195.
其他答案表明这是一个有效的ret指令,它在Linux中运行良好,但它在OSX上崩溃,因为默认情况下该部分被标记为不可执行.
为什么C++编译器不能告诉main()不是函数并且因链接器错误而停止?
main()有C链接,所以链接器不能区分符号的类型.在我们的例子中,_main驻留在数据部分.
start:
0000000100000eac pushq $0x00
0000000100000eae movq %rsp,%rbp
...
0000000100000c77 callq _main ; 1000010b0
0000000100000c7c movl %eax,%edi
0000000100000c7e callq 0x100000e16 ; symbol stub for: _exit
0000000100000c83 hlt
...
; the text section ends at 100000deb
Run Code Online (Sandbox Code Playgroud)
这不是一个合法的程序,但我认为标准对于是否需要诊断或者是未定义的行为有点模棱两可.(从实施的质量来看,我期待诊断.)