任何人都可以解释一下这个C ++代码的内容。它在Linux上编译并执行正常。
#include <iostream>
using namespace std;
int main = ( cout << "Hello world!\n", 195 );
答案 0 :(得分:68)
数字“195”是x86上RET指令的代码。
C ++编译器(在我的情况下是gcc)无法识别“main”未被声明为函数。编译器只看到有“主”符号,并假定它引用了一个函数。
C ++代码
int main = ( cout << "Hello world!\n", 195 );
正在文件范围初始化变量。此初始化代码在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.
答案 1 :(得分: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)
为什么要打印“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
答案 2 :(得分:5)
这不是一个合法的程序,但我认为标准对于是否需要诊断或者是未定义的行为有点模棱两可。 (从实施的质量来看,我期待诊断。)
答案 3 :(得分:1)
打印出 Hello world 后,它会将全局变量main
(整数)设置为值195。您仍然需要定义函数main来执行它。