【问题标题】:Compiling without main function (MacOS)无主函数编译(MacOS)
【发布时间】:2023-03-09 09:05:02
【问题描述】:

所以我正在尝试编译、链接和运行一个没有主函数的程序。这是代码:

#include <stdio.h> 
#include <stdlib.h>


int my_main() 
{ 
      printf("Hello world!\n"); 
          return 0; 

} 

void _start() 
{  
      exit(my_main()); 

} 

尝试使用以下命令进行编译:gcc -nostartfiles nomain.c。虽然它确实在 Debian vm 上编译并生成了 a.out 文件,但我无法在我的 macOS Catalina v10.15.2 中编译它。我正在使用最新版本的 gcc。我在尝试编译时收到的消息是:

架构 x86_64 的未定义符号:“_main”,引用自: 主要可执行文件 ld 的隐式入口/启动:未找到架构 x86_64 collect2 的符号:错误:ld 返回 1 退出状态

到目前为止,我已尝试将 _start 更改为 start,但仍然得到相同的结果。据我了解,编译过程因操作系统而异。

注意:这里没有我想解决的问题,只是好奇。

提前谢谢你

【问题讨论】:

  • 消息很清楚。操作系统预期 _main,您将其命名为 _start

标签: c macos gcc


【解决方案1】:

在带有 Xcode 11.3 的 macOS 10.14.6 上,问题中的代码编译并与命令链接:

clang -Wl,-e, -Wl,__start

生成的可执行文件似乎可以工作。但是,由于它绕过了 C 环境的启动代码,因此您不应期望使用 C 库中的例程或其他 C 功能可以正常工作。

请注意,上述命令中start之前需要两个下划线,因为源代码包含一个,另一个是由C编译器添加的。如果将代码更改为使用start 而不是_start,则该命令将使用一个下划线:

clang -Wl,-e, -Wl,_start

开关-Wl,-e, -Wl,_start-e _start 传递给链接器,它告诉链接器使用_start 作为要执行的初始代码的地址。我不清楚为什么这会绕过 C-run-time-startup 对象模块的默认加载,该模块还定义了_start。我宁愿使用一个链接器开关,告诉它不要加载该模块,但我在ld 的手册页中没有找到一个。实验表明,默认情况下,ld 加载默认对象模块,它引用main,这会导致链接错误,但是,当使用-e _start 时,链接器会将程序的_start 符号设置为启动地址,不加载默认对象模块。

【讨论】:

  • 您可以只列出所有选项和参数以使用单个 -Wl:clang -Wl,-e,_start 传递给链接器。
  • 很好的解释和总体回答,似乎这也适用于带有 -e 开关的 gcc。谢谢
【解决方案2】:

我很确定你可以在没有 main() 的情况下编译任何 C 源代码。

问题在于链接器试图创建一个可执行文件,如果没有 main(),它将无法工作。

【讨论】:

  • 你是对的,因为 gcc -c nomain.c 确实生成了一个目标文件,奇怪的是它在 Linux 上编译和链接得很好......
猜你喜欢
  • 2021-07-30
  • 1970-01-01
  • 1970-01-01
  • 2020-07-28
  • 2022-01-14
  • 2022-03-04
  • 1970-01-01
  • 2019-09-28
  • 1970-01-01
相关资源
最近更新 更多