问题 最小C程序中未定义的“main”引用


我正在尝试更深入地理解C编译,因此我正在编译和链接“手动”。这是我的代码

int main()
{
    return 0;
}

这是我放入我的控制台(Windows):

gcc -S main.c
as main.s -o main.o
ld main.o

在尝试链接时,我得到:

main.o:main.c:(text+0x7): undefined reference to `__main'

9532
2017-08-24 23:18


起源

跑 gcc -v main.c 查看编译器实际运行的命令。请注意,它运行的命令行要复杂得多 ld 比你给的那个。 - Jonathan Leffler
海湾合作委员会的时间极长 ld 参数并不总是强制性的。一个简单的 Hello, world 程序可以完美地链接到: ld -lc -lkernel32 src.o -o src.exe。 - Ryan B.
@RyanB我得到“找不到-lc”。 - Jack M
@RyanB,我担心这很大程度上取决于架构。 Main是一个普通的函数(没有任何特殊的东西)所以要调用它,你必须向链接器提供一段代码,从命令行收集实际参数,准备 argc 和 argv 参数,正确存储环境,然后拨打电话 main() 获取结果代码(以防万一 main() 做了 return exit_value;并做正确的事 _exit(2) 打电话(打完全部电话后 atexit(3) 注册电话)。这通常由模块完成 rt.o, crt.o等等,是拱门。 - Luis Colorado


答案:


您没有链接任何必要的支持库。像stdin,stdout,stderr这样的C全局对象不仅仅是从无处出现。命令参数和环境变量从操作系统中提取。退出所有这些 atexit() 函数被调用,返回代码来自 main 被传递给 exit(return_code)。等等。

看看命令 gcc -dumpspecsgcc -print-libgcc-file-name。查看该目录中的所有其他库。您会在dumpspecs的输出中找到很多引用的库和目标文件。我不知道究竟何时或如何解释这些规范规则,但你可能会得到这个想法。我认为GCC信息页面 info gcc 如果你深入挖掘,请详细解释。

info gcc 然后按'g'然后输入'Spec Files'

正如Jonathan Leffler所说,快捷方式是使用详细选项运行gcc: gcc -v 并看看它使用了什么命令。


12
2017-08-24 23:29



但如果问题是支持库,为什么未定义引用“__main”? - Jack M
@JackM这是完成实际工作的功能 main,见例如: gcc.gnu.org/onlinedocs/gccint/Collect2.html - deamentiaemundi
此外,如果您想深入了解ASM,一个好的做法是关闭优化(-O0标志)。这里没用,因为有任何功能和任何优化都可以,但我认为值得指出。 - Ryan B.
@JackM, __main 是实际的程序入口点。它与标识符不同 _main,这是内部的正常名称 main() 功能。 - Luis Colorado