试图了解GCC和Windows的主要功能

时间:2012-11-06 08:54:04

标签: c windows gcc export main

他们说 main()是一个像任何其他函数一样的函数,但是“标记”为二进制内部的入口点,操作系统可能会找到一个入口点( Don不知道如何)并从那里开始程序。所以,我试图找到更多关于这个功能的信息。我做了什么?我用这个代码创建了一个简单的.C文件:

int main(int argc, char **argv) {
     return (0);
}

我保存了文件,安装了GCC编译器(在Windows,MingW环境中)并创建了一个这样的批处理文件:

gcc -c test.c -nostartfiles -nodefaultlibs -nostdlib -nostdinc -o test.o
gcc -o test.exe -nostartfiles -nodefaultlibs -nostdlib -nostdinc -s -O2 test.o
@%comspec%

我这样做是为了获得一个非常简单的编译器和链接器,没有库,没有头,只是编译器。所以,编译顺利,但链接停止了这个错误:

test.c:(.text+0xa): undefined reference to '___main'
collect2.exe: error: Id returned 1 exit status

我认为主要功能是由链接器导出的,但我相信你不需要任何有关它的附加信息的库。但看起来确实如此。在我的情况下,我认为它必须是标准的GCC库,所以我下载了它的源代码并打开了这个文件: libgcc2.c 现在,我不知道这是否是构建主要功能以通过GCC链接的文件。事实上,我不明白GCC如何使用主要功能。为什么链接器需要gcc标准库? 要知道什么是主?我希望这使我的问题非常具体和明确。谢谢!

2 个答案:

答案 0 :(得分:5)

当gcc将所有目标文件(test.o)和库放在一起形成二进制文件时,它还会预先设置一个小对象(通常是crt0.o或crt1.o),它负责调用main()。当您在命令行上添加-v时,您可以看到gcc正在做什么:

  

$ gcc -v -o test.exe test.o

crt0 / crt1进行一些设置然后调用main。但是链接器最终负责根据操作系统构建可执行文件。使用-v,您还可以看到目标系统的选项。就我而言,它适用于Linux 64位:-m elf_x86_64。对于您的系统,这将类似于-m windows-m mingw

答案 1 :(得分:1)

发生错误是因为您使用以下两个选项:-nodefaultlibs -nostdlib

这些告诉GCC,它不应该将您的代码与包含真正调用libc.a的代码的c.lib / main()相关联。简而言之,每个操作系统都略有不同,大多数操作系统都不关心C和main()。每个都有自己特殊的方式来启动一个过程,其中大多数都与C API不兼容。

因此,C开发人员的解决方案是将“粘合代码”放入C标准库libc.a,其中包含操作系统期望的接口,创建标准C环境(设置内存分配结构,以便{ {1}}将映射操作系统的内存管理功能,设置stdio等)并最终调用malloc()

对于C开发人员来说,这意味着他们获得了main()的操作系统(以及编译器二进制文件),他们不需要关心设置的工作方式。

混淆的另一个原因是参考的名称。在大多数系统上,libc.a的符号名称为main()(即一个下划线),而_main是由设置代码调用的内部函数的名称,最终调用真实{{1} }}