假设我正在try 从以下位置创建可执行二进制文件:

// main.c

#include <stdio.h>

int main() {
    printf("Hello, world!");
    return 0;
}

我只需运行gcc main.c,就可以得到可执行的二进制a.out,它会打印出‘Hello,world!’,这是我想要的.

有人告诉我,gcc在这里做了两件事:

  1. main.c个编译成目标代码,
  2. 已将该代码与标准库联系起来,这样printf就可以工作了.

如何手动逐个手动完成这两个步骤?

我通过运行gcc -c main.c开始将main.c编译为目标代码,创建目标文件main.o.现在,我想要执行链接步骤.似乎我也可以用gcc来做这件事,只需运行gcc main.o,产生可执行的二进制a.out.

我读到这个gcc的第二次调用实际上是在幕后运行链接器ld.我如何使用ld而不是第二次调用gcc来实现这一点呢?如果我运行ld main.o,我得到一个警告和一个错误:

ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0
ld: main.o: in function `main':
main.c:(.text+0x10): undefined reference to `printf'

该错误似乎表明我需要告诉它链接到C标准库,这样我才能使用printf.我可以用-lc号旗帜ld main.o -lc号.这会产生a.out个结果,但我仍然收到警告:

ld: warning: cannot find entry symbol _start; defaulting to 00000000004002e0

当我运行a.out时,它会永远在屏幕上打印Hello, world!:

Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello, world!Hello,

What's the correct way to invoke 100 here to eliminate the warning and get the correct executable?

推荐答案

在这里调用ld以消除警告并获得正确的可执行文件的正确方式是什么?

only链接用户空间C二进制文件的正确方法是使用适当的编译器前端:gcc main.o.

直接使用ldnever是正确的.

你可以通过调用gcc -v main.o看到gcc实际上做了什么.但是请注意,结果ld(或collect2命令):

  • 可能会有所不同,具体取决于gcc的配置方式
  • 不同的操作系统版本可能会有所不同
  • 可能会有所不同,具体取决于使用的是哪个libc

TL;DR:欢迎您了解gcc如何在您的系统上调用ld,但是您不应该将结果放入任何Makefile或构建脚本中.

C++相关问答推荐

测量ARM MCU中断延迟的问题

为什么I2C会发送错误的数据?

为什么删除CAP_DAC_OVERRIDE后创建文件失败?

Win32API Wizzard97 PropSheet_SetWizButton不工作

在C++中通过空指针隐式访问常量变量的值

为什么中断函数会以这种方式影响数组?

C I/O:在Windows控制台上处理键盘输入

';\n&39;和';\r&39;中的';\n&39;之间有什么关系?

GCC错误,共享内存未定义引用?

我应该在递归中使用全局变量吗

在运行时判断C/C++指针是否指向只读内存(在Linux操作系统中)

为什么二进制文件的大小不会随着静态数据的大小而增加?

有没有办法减少C语言中线程的堆大小?

将char*数组深度复制到 struct 中?

从系统派生线程调用CRT

std::malloc/calloc/realloc/free 与纯 C 的 malloc/calloc/realloc/free 有什么不同

如何用用户输入的多个字符串填充数组?

使用fread()函数读取txt文件

如何在 C 中的 Postgres 函数的表中 for 循环

如何让 unlinkat(dir_fd, ".", AT_REMOVEDIR) 工作?