2010-06-07 156 views
11

两个共享库liba.so和libb.so. liba.so使用libb.so.所有的c文件都使用-fPIC编译。链接使用共享。当我们在liba.so上调用dlopen时,它无法在libb.so中找到符号...我们得到“未定义符号”错误。我们可以在没有错误的情况下将libb.so加密。我们知道liba正在查找libb,因为我们没有找到文件未找到的错误。当我们删除libb.so时,我们收到文件未找到错误。我们尝试过 - 没有运气。使用共享库的Linux共享库未定义符号

任何想法????

噢。 gcc 4.1.2

更新:我们在链接liba时使用rpath,因此它可以找到libb。

LDD liba.so返回:

linux-gate.so.1 => (0xffffe000) 
libb.so => ./libb.so (0xf6ef9000) <-------- LIBB 
libutil.so.1 => /lib/libutil.so.1 (0xf6ef5000) 
libdl.so.2 => /lib/libdl.so.2 (0xf6ef1000) 
libm.so.6 => /lib/libm.so.6 (0xf6ec9000) 
libpthread.so.0 => /lib/libpthread.so.0 (0xf6eb1000) 
librt.so.1 => /lib/librt.so.1 (0xf6ea8000) 
libc.so.6 => /lib/libc.so.6 (0xf6d62000) 
/lib/ld-linux.so.2 (0x007d0000) 

是它significat没有#在libb的端???

+1

您的意思是:您创建了两个库(-fPIC -shared),liba.so和libb.so. liba.so与libb.so是有联系的(或应该是......)并使用它。在程序X中,你可以在libb.so上尝试dlopen,并且一切正常;另一个测试程序Y试图dlopen liba.so,但它失败了,但是你知道liba.so正确地发现libb.so,因为你试图删除libb.so并且引发了另一个问题...你正在使用dlopen的选项? – ShinTakezou 2010-06-07 17:20:51

+0

你说得没错。现在我们不使用任何选项,因为dlopen是从我们无法控制的某个程序调用的。 – johnnycrash 2010-06-07 17:27:11

+0

命令'ldd liba.so'说什么? – 2010-06-07 18:01:17

回答

16

可以轻松地检查,其中libb.so预计将与ldd命令:

$ ldd liba.so 
    linux-gate.so.1 => (0xb77b0000) 
    libb.so.1 => not found 
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb75b6000) 
    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7572000) 
    libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb742b000) 
    /lib/ld-linux.so.2 (0xb77b1000) 

如果是not foundlibb.so的路径应该被添加到/etc/ld.so.conf或外壳可变LD_LIBRARY_PATH

另一种方法是在liba.so本身中设置rpath - 它基本上是对其路径进行硬编码,因此当二进制文件启动时,动态链接器将知道在哪里搜索共享库。

如果没有设置rpath,它将首先在LD_LIBRARY_PATH中搜索,然后在/etc/ld.so.conf(或/etc/ld.so.conf.d/)中提到路径。增加ls.so.conf后不要忘记执行/sbin/ldconfig

动态链接程序通过其soname(如果它被设置)搜索相关共享库 - 如果soname没有设置(与轮候册,-soname,libb.so.1为例如),它将按图书馆名称进行搜索。

例如:libb.so.1.0是您的实际图书馆,有soname - libb.so.1。一般来说,客户有以下文件结构:

libb.so -> libb.so.1 
libb.so.1 -> libb.so.1.0 
libb.so.1.0 

其中libb.solibb.so.1是符号链接。

根据libb.so,建立一些应用程序或其他库时,通常链接到libb.so

gcc -shared -Wl,-soname,liba.so.1 -o liba.so.1.2 -L/libb/path -lb 

当应用程序被启动(或执行的dlopen - 你的情况下) - 动态连接器将文件搜索与名libb.so.1 - 依赖库的soname,如果soname设置,不libb.so

这就是为什么你需要符号链接libb.so.1,指向实际的库。

如果使用ld.so.confldconfig,它将创建符号链接soname的名称,指向库文件,如果此符号链接丢失。

你可以看到ld-linux手册页获取更多有用的信息。


如果找到库,但一些符号的缺失,尝试 -Wl,--no-undefined选项

gcc -shared -Wl,-soname,libb.so.1 -Wl,--no-undefined -o libb.so.1.2 

应该给你一个错误,如果你错过了定义一些标志性建筑libb.so

+0

我们确实使用rpath。我们很确定它找到了这个库,因为我们在删除libb之后试图运行该应用程序,并且找到了文件未找到的错误。当我们用libb运行时,我们得到一个未定义的符号错误。 – johnnycrash 2010-06-07 17:51:54

+0

荣誉rpath ....但不是我们的问题。 – johnnycrash 2010-06-07 17:55:02

+0

我可能不了解关于soname的部分......你能澄清一点吗? – johnnycrash 2010-06-07 18:24:50

0

不要忘记,在链接所有目标库以生成可执行文件时,libs命令(all -lxxx参数)很重要(至少在gcc中)。

短例如:

LIBS = -L。 -ltest1 -ltest2

OBJS = code1.o code2.o

GCC $(LIBS)$(OBJS)-o mysoft

其可以在某些情况下会失败,而

GCC $(OBJS)-o mysoft $(LIBS)

不会