将库与不兼容的依赖关系链接 [英] Linking libraries with incompatible dependecies

查看:173
本文介绍了将库与不兼容的依赖关系链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个需要两个第三方库( libfoo.so libbar.so )的C ++项目。我的操作系统是Linux。

I'm working on a C++ project that needs two third party libraries (libfoo.so and libbar.so). My operating system is Linux.

libfoo.so 动态链接到libpng14.so.14(1.4.8) 1)

libfoo.so is dynamically linked to libpng14.so.14 (1.4.8) (EDIT 1)

libbar.so 似乎静态链接到 libpng的unknwon版本 libpng 1.2.8 (EDIT 1)

libbar.so seems to be statically linked to an unknwon version of libpng libpng 1.2.8 (EDIT 1)

我说似乎是因为:


  • ldd libbar.so 不会显示关于png的任何内容

  • nm -D libbar.so | grep png_read_png 说004f41b0 T png_read_png

  • 少libbar.so | grep png_read_png 说4577:004f41b0 738 FUNC GLOBAL DEFAULT 10 png_read_png

  • ldd libbar.so doesn't show nothing about png
  • nm -D libbar.so | grep png_read_png says "004f41b0 T png_read_png"
  • less libbar.so | grep png_read_png says "4577: 004f41b0 738 FUNC GLOBAL DEFAULT 10 png_read_png"

当我开始我的程序,它终止:

When i start my program, it abort:

terminate called after throwing an instance of 'char const*'

这是gdb backtrace:

This is gdb backtrace:

#0  0xb7ffd424 in __kernel_vsyscall ()
#1  0xb5e776a1 in raise () from /lib/libc.so.6
#2  0xb5e78de2 in abort () from /lib/libc.so.6
#3  0xb60a997f in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/gcc/i686-pc-linux-gnu/4.4.5/libstdc++.so.6
#4  0xb60a78a5 in ?? () from /usr/lib/gcc/i686-pc-linux-gnu/4.4.5/libstdc++.so.6
#5  0xb60a78e2 in std::terminate() () from /usr/lib/gcc/i686-pc-linux-gnu/4.4.5/libstdc++.so.6
#6  0xb60a7a21 in __cxa_throw () from /usr/lib/gcc/i686-pc-linux-gnu/4.4.5/libstdc++.so.6
#7  0xb5abf76d in ?? () from /usr/lib/libfreeimage.so.3
#8  0xb6fb9346 in png_error () from lib/libfsdk.so
#9  0xb6fa2a59 in png_create_read_struct_2 () from lib/libfsdk.so
#10 0xb6fa2b7a in png_create_read_struct () from lib/libfsdk.so
#11 0xb5abfa44 in ?? () from /usr/lib/libfoo.so
#12 0xb5aa766b in FreeImage_LoadFromHandle () from /usr/lib/libfreeimage.so.3
#13 0xb5aa59f6 in FreeImage_LoadFromMemory () from /usr/lib/libfreeimage.so.3
#14 0xb68a94a5 in Foo::Image::load (this=0xb4eff560, input=...)

正如你所看到的,异常抛出在属于libfoo.so的 Foo :: Image :: load

As you can see, exception is thrown in Foo::Image::load which belong to libfoo.so

停用我使用 libbar.so 的程式码部分,并移除连结, Foo :: Image :: load 精细。

Disabling the part of my code that uses libbar.so and removing linking to it, Foo::Image::load doesn't throw any exception and works fine.

编辑1

png_access_version_number )


  • 使用libbar.so linked, png_access_version_number() 10208 :版本1.2.8

  • 没有libbar.so linked, png_access_version_number() return 10408 :版本1.4.8

  • With libbar.so linked, png_access_version_number() return 10208: version 1.2.8
  • Without libbar.so linked, png_access_version_number() return 10408: version 1.4.8

推荐答案

由于您不能重建任何一个库,并且由于冲突的符号,不能允许库驻留在同一个动态链接器命名空间中,因此您唯一的选择是 isolate <

Since you can't rebuild either of the libraries, and since the libraries can not be allowed to reside in the same "dynamic linker namespace" due to conflicting symbols, your only choice is to isolate them.

您可以使用 dlopen(lib * .so,RTLD_LOCAL)对于其中一个或两个库),而不是直接链接到它们。

You can achieve that by using dlopen("lib*.so", RTLD_LOCAL) (for either or both of the libraries), instead of linking to them directly.

这可能是可行的,如果你只需要几个符号从例如 libfoo.so - 您可以直接使用 dlsym 而不是直接调用函数。

This could be workable if you only need a few symbols from e.g. libfoo.so -- you can simply use dlsym instead of calling the functions directly.

如果你对这两个库有太多的依赖,你的另一个解决方案可能是建立一个插件库。假设你想插入 libbar.so ,你需要 bar1() bar2 (),... ,bar1000()

If you have "too many" dependencies on both libraries, your other solution may be to build an "interposer" library. Let's say you want to interpose libbar.so, and you need bar1(), bar2(), ... bar1000() from it.

生成一个简单的Perl脚本)一个源文件,看起来像这样:

Write (or generate with a simple Perl script) a source file that looks like this:

static void *handle;
void *bar1()
{
   static void* (*pfn)(void *arg1, void *arg2, void *arg3, ..., argN);
   if (pfn == NULL) {
      if (handle == NULL)
        handle = dlopen("libbar.so", RTLD_LOCAL|RTLD_LAZY);
      pfn = dlsym(handle, "bar1");
   }
   return (*pfn)(arg1, arg2, ..., argN);
}
... repeat for all other libbar functions you depend on

现在编译并将此源链接到 libbar_interposer.so 并链接您的应用程序(这将不适用于 C ++ 名为mangling,仅用于plain - C )。 Voila,没有源应用程序的更改,你仍然有孤立的 libbar.so ,因此它的符号将不可见的应用程序的其余部分,特别是不会冲突与 libpng 中的任何符号。

Now compile and link this source into libbar_interposer.so and link your application against it (this will not work for C++ due to name mangling, only for plain-C). Voila, no source changes to the application, and you still have isolated libbar.so so its symbols will not be visible to the rest of the application, and in particular will not conflict with any symbols in libpng.

这篇关于将库与不兼容的依赖关系链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆