在C中_start()有什么用?

Sim*_*Guy 115 c

我从同事那里了解到,无需编写函数即可编写和执行C程序main().它可以在下面完成

withoutMain.c

/* Compile this with gcc -nostartfiles */

#include <stdlib.h>

void _start() {
  int ret = my_main();
  exit(ret); 
}

int my_main() {
  puts("This is a program without a main() function!");
  return 0; 
}
Run Code Online (Sandbox Code Playgroud)

将其编译为: my_main.c

运行方式为: main()

我的问题是,何时需要做这种事情?一些现实世界的场景?

fuz*_*fuz 95

符号_start是程序的入口点.也就是说,该符号的地址是程序启动时跳转到的地址.通常,具有名称的函数_start由一个文件提供,该文件crt0.o包含C运行时环境的启动代码.它设置一些东西,填充参数数组argv,计算有多少参数,然后调用main.后main返回时,exit被调用.

如果程序不想使用C运行时环境,则需要提供自己的代码_start.例如,Go编程语言的参考实现是这样做的,因为它们需要一个非标准的线程模型,这需要一些神奇的堆栈._start当你想编写非常小的程序或程序来做非传统的事情时,提供你自己的东西也很有用.

  • @SteveCox许多编程语言都是在C运行时之上构建的,因为以这种方式实现语言更容易.Go不使用普通的线程模型.它们使用小的堆分配堆栈和它们自己的调度程序.这肯定不是标准的线程模型. (6认同)
  • 另一个例子是Linux的动态链接器/加载器,它定义了自己的_start. (2认同)
  • @BlueMoon但是`_start`也来自对象文件`crt0.o`. (2认同)
  • @ThomasMatthews标准没有指定`_start`; 实际上,它没有指定在调用`main`之前发生了什么,它只是指定调用`main`时必须满足的条件.对于入口点来说,这更像是一个传统,它可以追溯到过去的"_start". (2认同)

Mik*_*eMB 43

main从程序员的角度来看,虽然它是程序_start的入口点,但是从操作系统的角度来看是常见的入口点(从OS启动程序后执行的第一条指令)

在典型的C和特别是C++程序中,在执行进入main之前已经完成了很多工作.尤其是全局变量的初始化. 在这里你可以找到一个很好的解释,在主要已经退出之间_start()main()之后发生的一切(见下面的评论).
它的必要代码通常由编译器编写者在启动文件中提供,但是使用该标志–nostartfiles你基本上告诉编译器:"不要打扰给我标准的启动文件,让我完全控制正在发生的事情.开始".

这有时是必要的,并且经常在嵌入式系统上使用.例如,如果您没有操作系统,则必须在初始化全局对象之前手动启用内存系统的某些部分(例如缓存).


uli*_*tko 6

这里很好地概述了之前 程序启动期间发生的情况main。特别是,它表明从操作系统的角度来看,它__start是您程序的实际入口点

它是程序中指令指针开始计数的第一个地址。

那里的代码调用一些 C 运行时库例程只是为了做一些内务处理,然后调用您的main,然后将事情放下并exit使用main返回的任何退出代码调用。


一张图片胜过千言万语:

C运行时启动图


PS:这个答案是从另一个问题移植过来的,SO 已经关闭了这个问题的副本。