【问题标题】:"undefined reference to symbol" error when using `ld` to link使用`ld`链接时出现“未定义的符号引用”错误
【发布时间】:2019-07-03 19:32:14
【问题描述】:

我是在 Linux 上编写程序的新手。我有一个使用shm_open、ftruncate、mmap、fork 和wait 的模块程序。我用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。

可能出了什么问题?

【问题讨论】:

  • 你能尝试用gcc -D_GNU_SOURCE -c编译吗? glibc 2.2.5 中有一个waitpid
  • 谢谢你,但是......不,它也不起作用......

标签: c glibc undefined-reference


【解决方案1】:

我用gcc -c编译了这个程序,然后把它和ld -lrt链接起来

在您更有经验之前,您不应尝试直接调用ld。相反,使用gcc(或cc)命令链接您的程序并对其进行编译。对于您的用例,这样的命令行:

gcc -o myprogram myprogram.o -lrt

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

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

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

为什么知道正确链接正常程序所需的所有这些额外参数的是gcc 命令而不是ld 命令?它主要是历史性的,但想法是 ld 是最小的,所以如果你正在做一些不寻常的事情(例如链接操作系统内核)你不需要关闭任何正常的东西关闭,你只需要从零开始并建立起来。但是,对于普通程序,人们可以使用(g)cc,而不必担心额外的参数。

顺便说一句,您在手册中找到的关于_XOPEN_SOURCE 的内容并不是关于如何使wait 在链接时可用;它是关于如何使wait 的声明 在编译 时可用。此外,您定义 _XOPEN_SOURCE 的值很重要。将其定义为 -D_XOPEN_SOURCE 而不是 -D_XOPEN_SOURCE=500 是您收到关于 ftruncate 的隐式声明的投诉的原因。

【讨论】:

  • 非常非常感谢!!有效!!只是为了澄清事实上,起初,我编译了 gcc -op pc (例如),但它说未定义对 shm_open() 和 shm_unlink() 的引用,然后我注意到 Link with -lrt 在 shm_open() 的手册中,我尝试过使用 gcc -Wl,-lrt 和 gcc -Wl, 等等(根据 gcc 手册将选项传递给链接器,但他们没有工作最后我只做了 gcc -c 然后 ld -lrt 解决了所描述的问题,现在我做了 gcc -op pc -lrt 并且它工作了!!非常感谢现在我尝试了
  • @SergioStarkloff -Wl,-lrt 如果你把它放在命令行的末尾而不是紧跟在gcc 之后,可能会起作用。为了将来参考,-Wl, 仅对gcc 程序无法识别的异常链接器选项是必需的。 -Wl,-lrt 在功能上与 -lrt 相同,因为 gcc 确实识别 -l 选项。
  • @SergioStarkloff 请参阅stackoverflow.com/a/43305704/388520,了解为什么-l 选项必须放在命令行末尾。
  • 谢谢你的朋友。你肯定是一名老师(但如果你不是......你应该是:-)
猜你喜欢
  • 1970-01-01
  • 2014-01-19
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 2019-11-25
  • 2012-07-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多