当前位置: > Linux教程 > Linux学习 >

linux下gcc In function `_start'

时间:2016-01-09 15:20来源:linux.it.net.cn 作者:IT
  没有main函数,,  
我们常用gcc main.c -o main命令编译一个程序,   
其实也可以分三步做,第一步生成汇编代码,第二步生成目标文件,第三步生成可执行文件:
$ gcc -S main.c     (注意S是大写的)
$ gcc -c main.s
$ gcc main.o

在main.c中这么写到:
#include
int m(){
printf("this is a test!");
return 0;
}
很明显,这个程序不能运行,因为没有main函数,试一下
gcc main.c -o main
报错:
[ming@localhost codetest]$ gcc main.c -o main
/usr/lib/gcc/i686-redhat-linux/4.5.1/../../../crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: ld 返回 1

整个程序的入口点是crt1.o中提供的_start,它首先做一些初始化工作(以下称为启动例程,Startup Routine),然后调用C代码中提供的main函数。所以,以前我们说main函数是程序的入口点其实不准确,_start才是真正的入口点,而main函数是被_start调用的。在_start中指名了要掉main,而程序中只有m函数,所以就运行不起来。
C程序的链接过程:


可以看到,,在生成main的可执行程序的时候,,其实还加入了其他的一些东西一起链接在一起执行的  main函数最标准的原型应该是int main(int argc, char *argv[]),也就是说启动例程会传两个参数给main函数,这两个参数的含义我们学了指针以后再解释。我们到目前为止都把main函数的原型写成int main(void),这也是C标准允许的,如果你认真分析了上一节的习题,你就应该知道,多传了参数而不用是没有问题的,少传了参数却用了则会出问题。
  由于main函数是被启动例程调用的,所以从main函数return时仍返回到启动例程中,main函数的返回值被启动例程得到,如果将启动例程表示成等价的C代码(实际上启动例程一般是直接用汇编写的),则它调用main函数的形式是:

exit(main(argc, argv));
  也就是说,启动例程得到main函数的返回值后,会立刻用它做参数调用exit函数。exit也是libc中的函数,它首先做一些清理工作,然后调用上一章讲过的_exit系统调用终止进程,main函数的返回值最终被传给_exit系统调用,成为进程的退出状态。我们也可以在main函数中直接调用exit函数终止进程而不返回到启动例程,例如:

#include  int main(void) { exit(4); }
  这样和int main(void) { return 4; }的效果是一样的。在Shell中运行这个程序并查看它的退出状态:

$ ./a.out
$ echo $?
4
  按照惯例,退出状态为0表示程序执行成功,退出状态非0表示出错。注意,退出状态只有8位,而且被Shell解释成无符号数,如果将上面的代码改为exit(-1);或return -1;,则运行结果为

$ ./a.out
$ echo $?
255

(责任编辑:IT)
------分隔线----------------------------