Zan*_*ynx 48

操作系统调用该main()函数.实际上,它通常会调用其他名为奇怪的东西_init.C编译器将标准库链接到提供此操作系统定义的入口点然后调用的每个应用程序main().

编辑:显然这对某些人来说不够详细和正确.

许多Unix OS使用的可执行和可链接格式(ELF)定义了入口点地址.这是程序在操作系统完成exec()调用后开始运行的地方.在Linux系统上,这是_init.

来自objdump -d:

Disassembly of section .init:

08049f08 <_init>:
 8049f08:       55                      push   %ebp
 8049f09:       89 e5                   mov    %esp,%ebp
 8049f0b:       83 ec 08                sub    $0x8,%esp
 8049f0e:       e8 a1 05 00 00          call   804a4b4 <call_gmon_start>
 8049f13:       e8 f8 05 00 00          call   804a510 <frame_dummy>
 8049f18:       e8 d3 50 00 00          call   804eff0 <__do_global_ctors_aux>
 8049f1d:       c9                      leave  
 8049f1e:       c3                      ret    
Run Code Online (Sandbox Code Playgroud)

来自readelf -d:

 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000c (INIT)                       0x8049f08
 0x0000000d (FINI)                       0x804f018
 0x00000004 (HASH)                       0x8048168
 0x00000005 (STRTAB)                     0x8048d8c
 0x00000006 (SYMTAB)                     0x804867c
 0x0000000a (STRSZ)                      3313 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000015 (DEBUG)                      0x0
 0x00000003 (PLTGOT)                     0x8059114
 0x00000002 (PLTRELSZ)                   688 (bytes)
 0x00000014 (PLTREL)                     REL
 0x00000017 (JMPREL)                     0x8049c58
 0x00000011 (REL)                        0x8049be0
 0x00000012 (RELSZ)                      120 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x6ffffffe (VERNEED)                    0x8049b60
 0x6fffffff (VERNEEDNUM)                 3
 0x6ffffff0 (VERSYM)                     0x8049a7e
 0x00000000 (NULL)                       0x0
Run Code Online (Sandbox Code Playgroud)

您可以看到INIT等于_init的地址.

frame_dummy和__do_global_ctors_aux的代码位于一组名为crtbegin.o和crtend.o的文件中(以及这些名称的变体).这些是GCC的一部分.该代码为C程序执行各种必要的操作,例如设置stdin,stdout,全局和静态变量等.

下面的文章很好地描述了它在Linux中的作用(摘自下面的答案,投票少):http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html

我相信别人的回答已经描述了Windows的作用.

  • 它不会调用`_init`或任何其他.它调用入口点地址.它可以在任何地方. (4认同)
  • `__start`,呜. (2认同)
  • @ZanLynx 你怎么知道?我怎么知道?为什么不直接看一个 C 程序呢?C 和C++ 是截然不同的语言,程序启动是可见的区域之一(例如调用构造函数)。 (2认同)

And*_*rey 24

最终它是操作系统.通常在实入入口点和主要函数之间存在一些介质,这由编译器链接器插入.

一些细节(与Windows相关):PE文件中有一个标题,IMAGE_OPTIONAL_HEADER其中包含字段AddressOfEntryPoint,该字段又是将要执行的文件中第一个代码字节的地址.

  • 它不是由编译器插入的,而是由链接器插入的,通常是通过链接到诸如`crt.a(crt.o)`或`crt.lib(crt.obj)`之类的东西,它们通常是诸如`libc之类的东西的一部分.a`或`c.lib`。 (2认同)

use*_*302 9

http://coding.derkeiler.com/Archive/C_CPP/comp.lang.c/2008-04/msg04617.html

  • @Zack通常在这里发布没有某种摘要的链接是不受欢迎的 (6认同)

Pau*_*han 7

操作系统调用main.可重定位可执行文件中将有一个指向main位置的地址(有关更多信息,请参阅Unix ABI).

但是,谁称之为操作系统?

"RESET"信号上的中央处理单元(在通电时也断言)将开始在给定地址(例如,0xffff)的某些ROM中查找其指令.

通常会向BIOS发出某种跳转指令,它会配置内存芯片,加载基本硬盘驱动程序等等.然后读取硬盘驱动器的引导扇区,然后启动下一个引导加载程序,它加载包含如何读取的基本信息的文件,比如NTFS分区以及如何读取内核文件本身.将设置内核环境,加载内核,然后 - 然后! - 内核将跳转到执行.

完成所有艰苦工作后,内核可以继续加载我们的软件.


Dre*_*ins 5

操作系统调用C运行时(CRT)中包含的函数并链接到您的可执行文件中.称之为"CRT主".

CRT main做了一些事情,其中​​最重要的两件事,至少在C++中,要运行一系列全局C++类并调用它们的构造函数,并调用main()函数并将其返回值赋给shell .

如果内存服务,Visual C++ CRT main还会做更多的事情.它配置内存分配器,如果使用Debug CRT来帮助查找内存泄漏或错误访问,这一点非常重要.它还在结构化异常处理程序中调用main ,它捕获错误的内存访问和其他崩溃并显示它们.


小智 5

也许您的问题的最佳信息可以在下面提到的链接 http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html中找到,这是迄今为止我遇到的最好的信息。