在这个C ++代码中发生了什么?

任何人都可以请解释一下这个C ++代码。 它在Linux上编译和执行得很好。

#include <iostream> using namespace std; int main = ( cout << "Hello world!\n", 195 ); 

数字“195”是x86上RET指令的代码。

C ++编译器(在我的情况下,gcc)无法识别“main”没有被声明为一个函数。 编译器只看到有“主”符号,并假设它是指一个函数。

C ++代码

 int main = ( cout << "Hello world!\n", 195 ); 

正在文件范围初始化一个variables。 这个初始化代码在C / C ++环境调用main()之前执行,但在初始化“cout”variables之后执行。 初始化打印“Hello,world!\ n”,并将variables“main”的值设置为195.完成所有初始化后,C / C ++环境调用“main”。 程序立即从这个调用中返回,因为我们在RETURN指令(代码195)的地址是“main”。

示例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. 

这不是一个有效的C ++程序。 事实上,在打印“Hello World”之后,它在Mac OSX上崩溃了。

反汇编显示main是一个静态variables,并且有它的初始化器:

 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 ,static整型variables的静态初始化期间运行。 在C ++运行时甚至试图调用main()之前调用静态初始化器。 当它发生崩溃时,因为main不是一个有效的函数,所以可执行文件的数据部分只有一个整数195。

其他答案表明这是一个有效的ret指令,它在Linux中运行良好,但是在OSX上崩溃,因为该部分在默认情况下被标记为不可执行。

为什么C ++编译器不能告诉main()不是一个函数,并停止链接器错误?

main()有C链接,所以链接器不能区分这些符号的types。 在我们的例子中, _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 

这不是一个合法的程序,但是我认为这个标准对于是否需要诊断或者是不确定的行为有点含糊不清。 (从实施的angular度来看,我希望能有一个诊断。)

打印完Hello world后,将全局variablesmain (一个整数)设置为195。 您仍然需要定义要执行的函数main。