我是刚开始在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
版。
怎么了?
答案 0 :(得分:6)
我用
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
的定义。 (不要只是自己尝试将-lc
粘贴在ld
命令行上。实际上,请尝试一下。您会发现您只会得到更神秘的错误消息,可能类似于{{1 }}或warning: cannot find entry symbol _start
或什至知道的人。)
如果您好奇的话,可以通过在上面的undefined reference to __bswapsi2
调用中添加-v
来查看所有这些额外的参数是什么,但这很麻烦,只有编译器开发人员才需要担心大部分。
为什么gcc
命令而不是gcc
命令知道正确链接普通程序所需的所有这些额外参数?它主要是历史性的,但是想法是ld
很小,因此,如果您做一些不寻常的事情(例如,链接操作系统内核),则无需关闭任何正常的 ,您只需要从零开始就可以建立。但是,对于普通程序,人们可以使用ld
,而不必担心额外的参数。
顺便说一句,您在手册中找到的关于(g)cc
的内容与在链接时如何使_XOPEN_SOURCE
无关。这是关于如何在 compile 时使wait
的声明可用的。同样,您定义wait
的值也很重要。将其定义为_XOPEN_SOURCE
而不是-D_XOPEN_SOURCE
的原因就是您抱怨隐式声明-D_XOPEN_SOURCE=500
。