静态库和共享库的符号冲突问题?

7
我正在处理一个使用FreeImage和openCV的项目,目前我们都在使用jpeg支持(我正在努力修复它,但现在必须保留)。 FreeImage将libjpeg 7.0编译到其静态库中,而openCV的highgui库将其链接到共享库中(在我的系统上,Ubuntu 9,我安装了libjpeg 6.2)。
它们链接到最终库中,用于链接到各种程序、Java包装器等。所有这些工作都很好,在编译/链接时没有符号冲突或任何问题。然而,当我尝试使用openCV cvLoadImage函数打开图像时,它在读取标头时崩溃了,很可能是由于6.2和7.0之间标头的差异所致。
如果我取消连接FreeImage(并注释掉需要它的代码),则openCV调用开始重新工作,因此显然FreeImage的静态libjpeg符号与从libjpeg共享库加载的符号发生冲突。我无法弄清楚的是,为什么我的编译器在链接时没有因两组libjpeg符号而抛出错误。此外,我已经尝试暂时使用7.0版本替换系统的jpeglib.h头文件,看看是否可以使与freeimage提供的符号同步的openCV编译,但似乎没有成功。
最后,我在freeimage编译的libjpeg的jpeg_read_header中放置了一个printf,并重新构建它,以查看openCV是否使用freeimage libjpeg定义。它没有打印出来,所以我必须假设没有。
所以我的问题是:
1)为什么连接静态libjpeg和共享的libjpeg不会生成由于重复符号而导致的链接错误?
2)有人知道为什么这两个东西会相互冲突吗?
编辑:以调试模式编译openCV,然后再次以常规模式编译似乎已经解决了问题,不知道发生了什么事。
3个回答

6

一般来说,连接器接受传递多个库的参数,这些库都可以解析相同的符号。它只会使用找到的第一个库文件,链接器命令行中库文件的顺序将决定哪一个“获胜”。

顺便提一下,对于目标文件来说则不是这样。我使用过的每个连接器都假定您想要使用指定的所有目标文件,如果有多个目标文件具有相同的符号,则会出现错误提示。


那么很有可能会出现其中一个版本的libjpeg会“胜出”,对吧?因此,要么它会选择openCV的版本,在这种情况下,一切都能正常工作,或者在编译期间切换openCV使用的头文件到freeimage应该可以解决问题......但是事实并非如此。=( - gct
如果链接器选择的库与您使用的头文件不同,那么我预计它将无法正常工作。您需要切换头文件并重新排列链接行上的库,即使如此也可能会失败。最好完全从链接行中省略您不想使用的库。 - John Knoeller

2

1

就像这样

静态库是在编译时编译的,动态库是在运行时加载的,但只有缺失的符号才会被加载(我想是这样)。您可以将共享库编译进去,然后可能会出现符号冲突。

因此,opencv使用已经存在的编译符号,而不是来自动态库的符号。从opencv的角度来看,您最终会使用静态符号,可能具有不同的签名。


我的假设是它正在使用其中一个库,但也许它以某种方式同时使用了两个库?改变openCV编译的头文件后,问题并没有得到解决。 - gct

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接