【问题标题】:How the compiler knows where my main function is?编译器如何知道我的主要功能在哪里?
【发布时间】:2015-06-26 07:06:11
【问题描述】:

我正在开发一个包含多个模块(源文件、头文件、库)的项目。所有汤中的一个文件包含我的主要功能。

我的问题是:

  • 编译器如何知道哪些模块要编译,哪些不?
  • 编译器如何识别里面有main()的模块?

【问题讨论】:

  • 阅读编译器的各个阶段,你就会得到答案。
  • 它没有。 [此评论的enuf字符]
  • 编译器不关心主函数,会编译所有编译单元。稍后的链接器将链接这些并可能删除未链接的函数。
  • 这是链接器的职责。 Makefile 会处理它。

标签: c main


【解决方案1】:

编译器本身并不关心什么文件包含哪些函数; main() 并不特别。但是,在链接阶段,来自不同文件(可能还有编译单元)的所有这些符号都会匹配。链接器有一个隐藏的“模板”,它的代码位于固定地址,当您运行程序时操作系统将始终调用该模板。该代码将调用您的main;因此,链接器在所有文件中查找main。如果它不存在,你会得到一个未解决的符号错误,就像你使用了一个忘记实现的函数一样。

main 的任何其他功能相同:您只能有一个 实现;在两个链接在一起的文件中有两个main,您会收到链接器错误,因为链接器无法决定使用哪一个。

【讨论】:

  • 更具体地说:在链接模式下调用编译器时,它充当驱动程序,引用C库的特殊运行时代码。可执行文件头中的固定地址通常是名为_start 的符号的地址。
【解决方案2】:

编译器如何知道哪些模块要编译,哪些不是

它没有。你告诉你想要编译哪些,通常是通过makefile中的编译语句。

编译器如何识别里面有main()的模块?

总的来说,这是一个很大的过程,已经在this related question 中回答了。

总而言之,在使用标准 C 库编译程序时,程序的入口点设置为 _start。现在它在内部引用了main() 函数。因此,在编译时,没有(不需要)检查main() 的存在。在链接时,链接器应该能够找到它可以链接到的main()一个 实例。这样,main() 将作为您程序的入口点。

所以,回答

编译器如何知道我的 main 函数在哪里?

它确实(并且不需要)。具体来说,这是链接器的工作。

【讨论】:

    【解决方案3】:

    启动程序的汇编代码(通常被嵌入的人称为启动代码)专门调用main()
    main() 的原型包含在编译器文档中。 编译程序时,会生成一个目标文件。然后将源代码中的目标文件与启动运行时组件(通常称为 crt0.o[bj])和 C 库组件等链接。 如果将main() 更改为无法识别的签名,编译单元将抱怨对_main__main 的外部引用未解析。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多