"undefined reference to symbol" 使用 `ld` 到 link 时出错

"undefined reference to symbol" error when using `ld` to link

我是在 Linux 上编写程序的新手。我有一个使用 shm_openftruncatemmapforkwait 的单个模块程序。我用 gcc -c 编译了这个程序,然后用 ld -lrt 链接它(shm_open 需要 librt),我得到了一个奇怪的链接器错误:

undefined reference to symbol 'waitpid@@GLIBC_2.2.5'

wait 的联机帮助页说

Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
   waitid():
       Since glibc 2.26: _XOPEN_SOURCE >= 500 ||
           _POSIX_C_SOURCE >= 200809L
       Glibc 2.25 and earlier:
           _XOPEN_SOURCE

但是将 #define _XOPEN_SOURCE 放入代码中并没有帮助,如果我这样做了

gcc -c -D _XOPEN_SOURCE 

编译器说 ftruncate.

的隐式声明

我在VMWare下运行Ubuntu。 GCC 版本为 gcc (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609.

有什么问题吗?

I compiled this program with gcc -c and then linked it with ld -lrt

除非您更有经验,否则不应尝试直接调用 ld。相反,link 您的程序,以及使用 gcc(或 cc)命令编译它们。对于您的用例,命令行如下:

gcc -o myprogram myprogram.o -lrt

应该可以。 (请注意 -lrt 的位置;在大多数情况下,由于乏味的历史原因,-l 选项需要在命令行上 之后 目标文件。)

在后台,当您 link 使用 gcc 命令的程序时,它会为您运行 ld,但它包含 一大堆 的附加参数。这些都是构造普通程序所必需的,而且它们足够复杂,普通程序员不必担心它们。额外的参数之一是 -lc,告诉 ld 包含 C 运行时库的核心,它提供了 link 中缺少的 waitpid@@GLIBC_2.2.5 的定义。 (不要只是尝试自己在 ld 命令行上粘贴 -lc。实际上,请尝试一下。您会发现您只会收到更神秘的错误消息,可能类似于 warning: cannot find entry symbol _startundefined reference to __bswapsi2 或者谁知道。)

如果你好奇的话,你可以通过在上面的 gcc 调用中添加一个 -v 来查看所有这些额外的参数是什么,但这是一团糟,只有编译器开发人员需要担心大部分。

为什么 gcc 命令而不是 ld 命令知道所有这些额外的参数,你需要正确地 link 一个正常的程序?它主要是历史的,但想法是 ld 是最小的,所以如果你正在做一些不寻常的事情(例如 linking 操作系统内核)你不需要把任何东西变成正常的 off,你只需要从零开始,不断积累。但是,对于普通程序,人们可以使用 (g)cc 而不必担心额外的参数。

顺便说一下,您在手册中找到的关于 _XOPEN_SOURCE 的内容并不是关于如何在 link 时间使 wait 可用;它是关于如何使 wait 声明 编译 时可用。此外,您定义的值 _XOPEN_SOURCE 很重要。将其定义为 -D_XOPEN_SOURCE 而不是 -D_XOPEN_SOURCE=500 是您收到有关 ftruncate.

隐式声明的投诉的原因