3

我正在向系统添加两个类和库,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定义符号的位置。但是从库日志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。此处链接是否缺少任何信息?看起来孩子只包括父母的头文件。

编辑2

经过另一次测试,调用

_handle = dlopen("parent.so", RTLD_NOW|RTLD_GLOBAL);

之前的崩溃线会解决问题,我认为这意味着最初parent.so没有加载。但我仍然不太清楚原因。

4

3 回答 3

4

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

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

请注意,顺序很重要。指定-lparent所有目标文件。您可能还需要通过-Wlg++ 的选项将其他选项传递给链接器。

那可能还不够好。您可能需要将包含的库添加libparent.soLD_LIBRARY_PATH环境变量中。

几个陷阱:如果你没有用lib前缀命名这些库,你会混淆链接器。如果您不使用任何一个编译源文件,-fPIC或者-fpic您将没有可重定位的对象。

附录
依赖于其他库的库存在很大的潜在问题。假设您在编译子库源文件时使用 1.5 版的父包。你设法克服了所有的库依赖问题。您已指定您的libchild.so依赖于libparent.so. 你的东西刚刚好。直到父包的 2.0 版本出来。现在你的东西在任何地方都被破坏了,而且你没有改变任何一行代码。

解决这个问题的方法是在构建子库时指定生成的共享库具体依赖于 libparent.so 的 1.5 版。

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

-soname=libparent.so.1.5请注意:在构建 libparent.so 时需要使用该选项。这就是让系统表示您的 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,而不是破坏一切的闪亮的新版本。

于 2012-10-18T04:30:16.150 回答
1

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

g++ -shared -o libparent.so parent.o
g++ -shared -o libchild.so -lparent child.o
于 2012-10-18T01:33:53.297 回答
-1

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

将它们的名称更改为 libparent.so 和 libchild.so。

然后用这样的东西编译:

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

编辑:

尝试在 child.so 之前加载 parent.so 可能会是一个较小的变化。你已经试过了吗?

于 2012-10-18T01:25:38.113 回答