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

时间:2011-10-05 10:46:50

标签: c++

任何人都可以解释一下这个C ++代码的内容。它在Linux上编译并执行正常。

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

4 个答案:

答案 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来执行它。