即使在链接具有定义的库之后,也会出现“未定义的函数引用”问题

时间:2018-05-21 09:31:45

标签: c gcc linker-errors undefined-reference

我正在尝试使用.o,.so,.a文件创建可执行文件。

这是我的构建命令: -

pkgs/gcc/v4.8.3/bin/gcc -L/usr/X11R6/lib -O2 -DUSE_FLEX -Wall -Wno-char-subscripts -fPIC -DLINUX -DG_DISABLE_CONST_RETURNS -fno-strict-aliasing -o ../build/kl/Release/test/bin/pure.exe -L../build/kl/Release/test/modules ../build/kl/Release/test/maker/constrfunc.TCL.o ../../build/kl/Release/test/maker/pvdbprocs.TCL.o .. ../build/kl/Release/test/maker/maker/memmaker.TCL.o .. ../build/kl/Release/test/maker/modules/libdenbase.a .. ../build/kl/Release/test/maker/guibase.o -litk3.2 -litcl4.0.0 -ltk8.3 -lcdnviptcl8.4 -litclstub4.0.0 -ldenbase -lglib-2.0 -ldenbase -lX11 -ldl -lm -lviputil -lvippli -lcdsCommonMT_sh -lpthread  -L/home/dlb/extlibs/arm/lib 

我有一些库,它们在路径“-L / home / dlb / extlibs / arm / lib”中定义了函数。还是在下面抛出错误。

错误:

../build/kl/Release/test/maker/guibase.o: In function `decodeAddrList':
tree234.c:(.text+0xc): undefined reference to `ptritclStubsPtr'
tree234.c:(.text+0x20): undefined reference to `ptrlitclStubsPtr'
tree234.c:(.text+0x12c): undefined reference to `ptrlitclStubsPtr'
tree234.c:(.text+0x140): undefined reference to `ptrlitclStubsPtr'

我在库中的符号位于path / home / dlb / extlibs / arm / lib: -

命令: -

readelf -s libitcl4.0.0.so | grep ptrlitclStubsPtr

348: 0000000000060f10     8 OBJECT  LOCAL  DEFAULT   24 ptrlitclStubsPtr

我在这里错过了什么吗?

注意,OP在同一问题的转贴中提供了更多信息;
OP的评论引用:
“由于一些隐私问题......我正在重命名这些符号......它是由我编辑的......这是错字......我刚刚纠正了它...... :)” 即错误消息中的标识符和grep行以及grep行的输出已被手动更改。

1 个答案:

答案 0 :(得分:1)

您所询问的功能似乎是 local 到定义它们的文件。也就是说,看起来它们显然不是(甚至不允许)从外部调用的。

也就是说,共享库libitcl4.0.0.so的源代码中的某个位置可能会出现如下声明:

static tclStubs *ptrlitclStubsPtr;

该关键字static表示结果符号ptrlitclStubsPtr可见性仅限于其自己的源文件。

我从所报告的readelf输出包含行

这一事实推断出所有这一切
348: 0000000000060f10     8 OBJECT  LOCAL  DEFAULT   24 ptrlitclStubsPtr

该标志LOCAL表示该符号是本地的。如果它是全局的,有意(并且能够)在外部调用,则会出现标记GLOBAL

为什么变量是私有的(static),所以你不能使用它们?它是一个软件工程的东西,"信息隐藏",旨在减少"宽度"您和libitcl4之类的库之间的接口。私有的符号与libitcl4中的实现决策密切相关,的决定应该对调用者可见或者任何关注。它认为,如果调用者能够访问这些符号,则调用者还必须知道其他实现细节,这意味着libitcl4的作者将无法在不中断的情况下更改这些实现细节(使呼叫代码无效。因此,为了防止这种情况,通常会做出选择,使调用者无法以这种方式变得依赖。

在这种情况下,你基本上有三条前进道路:

  1. static的源中的变量声明中删除libitcl4.0.0.so标记。 (这显然要求您可以访问libitcl4.0.0.so的来源,以及重建它的能力。它也可能是一个非常糟糕的主意。正如我所解释的那样,这些符号可能是静态是有充分理由的。)

  2. libitcl4.0.0.so中添加一个新功能,它可以完成您需要做的任何事情,并且由于它在同一源文件中的位置,可以访问这些符号。 (这也要求您有权访问并重建``libitcl4.0.0.so`。)

  3. 使用libitcl4.0.0.so的现有公共设施,找到其他一些做任何事情的方法。