查找符号时,程序不会从正确的库中搜索

时间:2012-10-18 00:39:46

标签: c++ linux runtime shared-libraries dynamic-loading

我正在向系统添加两个类和库,parent.sochild.so从中派生出来。

问题是当程序加载child.so时,它无法从parent.so找到父虚拟函数的定义。

会发生什么,

nm -D child.so会给出类似的内容(我只是更改了名称)

U _ZN12PARENT15virtualFunctionEv


程序将崩溃

_handle = dlopen(filename, RTLD_NOW|RTLD_GLOBAL); //filename is child.so

它会在LD_DEBUG = libs

时出错
symbol lookup error: undefined symbol: _ZN12PARENT15virtualFunctionEv (fatal)

我无法解释的是,我尝试LD_DEBUG = symbols使用GDB,在运行dlopen时,日志显示它试图在系统中除parent.so以外的所有库中查找,符号定义的位置。但是从libs中已经加载了日志parent.so并运行了代码,它与所有其他库的路径相同。

 ......
 27510:     symbol=_ZN12PARENT15virtualFunctionEv;  lookup in file=/lib/tls/libm.so.6
 27510:     symbol=_ZN12PARENT15virtualFunctionEv;  lookup in file=/lib/tls/libc.so.6
 27510:     symbol=_ZN12PARENT15virtualFunctionEv;  lookup in file=/lib/ld-linux.so.2
 27510:     child.so: error: symbol lookup error: undefined symbol: _ZN12PARENT15virtualFunctionEv(fatal)

程序或系统如何管理哪个库来查找符号的定义?

我是Linux的新手,有人可以指点我的工作方向吗?

感谢。

修改

用于生成parent.so文件的命令是

c++  -shared  -o parent.so parent.o

类似于child.so。在这里链接是否缺少任何信息?看起来孩子只包含父母的头文件。

EDIT2

经过另一次测试,请致电

_handle = dlopen("parent.so", RTLD_NOW|RTLD_GLOBAL);
崩溃线之前的

将解决问题,我认为最初意味着parent.so未加载。但我仍然不清楚原因。

3 个答案:

答案 0 :(得分:4)

您需要告诉链接器您的库libchild.so使用libparent.so中的功能。您在创建子库时执行此操作:

g++ -shared -o libchild.so child_file1.o child_file2.o -Lparent_directory -lparent

请注意,订单很重要。在所有目标文件之后指定-lparent。您可能还需要通过g ++的-Wl选项将其他选项传递给链接器。

这仍然可能不够好。您可能需要将包含libparent.so的库添加到LD_LIBRARY_PATH环境变量。

一些问题:如果您没有使用lib前缀命名这些库,则会使链接器大大混淆。如果您没有使用-fPIC-fpic编译源文件,则不会有可重定位目标文件。

<强>附录
依赖于其他库的库存在很大的潜在问题。假设在编译子库源文件时使用父包的1.5版。您设法克服了所有库依赖项问题。您已指定libchild.so取决于libparent.so。你的东西才有效。这是在父包的2.0版出来之前。现在你的东西在任何地方都会被破坏,你没有改变过一行代码。

解决此问题的方法是在构建子库时指定生成的共享库特别依赖于libparent.so`的1.5版。

要执行此操作,您需要通过-Wl选项将选项从g ++ / gcc传递到链接器。使用-Wl,<linker_option>,<linker_option>,...如果这些链接器选项需要空格,则需要在g ++命令中对它们进行反斜杠转义。一些关键选项是-rpath-soname。例如,-rpath=/path/to/lib,-soname=libparent.so.1.5

请注意:构建libparent.so时需要使用-soname=libparent.so.1.5选项。这就是系统表示你的libchild.so(版本1.0)依赖于libparent.so(版本1.5)的原因。而且你没有构建libparent.so。您构建libparent.so.1.5。 libparent.so怎么样?这需要存在,但它应该是libparent.so的某些编号编号版本(最好是最新版本)的符号链接。

现在假设编译了非向后兼容的父版本2.0并将其内置到一个闪亮的新libparent.so.2.0中,libparent.so象征性地链接到这个闪亮的新版本。使用笨重的旧libchild.so(版本1.0)的应用程序将很乐意使用笨重的旧版libparent.so而不是破坏一切的闪亮新版本。

答案 1 :(得分:1)

看起来你没有告诉链接器child.so需要parent.so,使用如下内容:

g++ -shared -o libparent.so parent.o
g++ -shared -o libchild.so -lparent child.o

答案 2 :(得分:-1)

构建主程序时,必须告诉编译器它与这些库链接;这样,当它启动时,linux将为它加载它们。

将其名称更改为libparent.so和libchild.so。

然后用这样的东西编译:

g++ <your files and flags> -L<folder where the .so's are> -lparent -lchild

编辑:

在child.so之前尝试加载parent.so可能是一个较小的更改。你有没试过?