极简C程序中出现“main”未定义的引用错误

12

我试着更深入地理解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'

3
运行gcc -v main.c命令可以查看编译器实际运行的命令。请注意,对于ld,它运行的命令行比您提供的命令复杂得多。 - Jonathan Leffler
1
GCC的极长的ld参数并不总是必需的。一个简单的“Hello, world”程序可以通过以下方式完美地链接:ld -lc -lkernel32 src.o -o src.exe - Ryan B.
@RyanB 我得到了“无法找到-lc”的错误。 - Jack M
1
@RyanB,我怕这取决于架构。Main是一个普通函数(没有任何特殊之处),因此为了调用它,您必须向链接器提供一段代码,该代码从命令行进行实际参数收集,准备argcargv参数,正确存储环境,然后调用main()获取结果代码(如果main()执行return exit_value;),并进行适当的_exit(2)调用(在调用所有atexit(3)注册调用之后)。这通常由模块如rt.ocrt.o等完成,并且是与架构相关的。 - Luis Colorado
1个回答

12

你没有链接任何必要的支持库。C全局对象,如stdin、stdout、stderr,并不会自己出现。命令参数和环境变量是从操作系统中获取的。在退出时,所有的atexit()函数都会被调用,而main的返回代码将传递给exit(return_code)。 等等。

检查命令gcc -dumpspecsgcc -print-libgcc-file-name。看看该目录中的所有其他库。你会发现许多这些库和目标文件在dumpspecs的输出中引用。我不知道这些规则是什么时候或者如何被解释的,但是你可能可以得到这个想法。如果你深入挖掘,我认为GCC信息页面info gcc会详细解释它。

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

正如Jonathan Leffler所说,快捷方式是使用verbose选项运行gcc:gcc -v,然后查看它使用了哪些命令。


但如果问题是支持库,为什么会出现对“__main”的未定义引用? - Jack M
@JackM 这是 main 函数中实际工作的函数,例如:https://gcc.gnu.org/onlinedocs/gccint/Collect2.html - deamentiaemundi
另外,如果您想深入了解汇编语言,一个好的实践是关闭优化(-O0标志)。在这里,由于没有任何函数和任何需要进行的优化,它是无用的,但我认为值得指出。 - Ryan B.
1
@JackM,__main是实际的程序入口点。它不是与main()函数的内部正常名称相同的标识符_main - Luis Colorado

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接