【发布时间】:2019-06-14 08:41:22
【问题描述】:
我的应用程序在 Linux 上动态链接的库 (libpng) 出现问题。
我使用的 libpng 版本是 libpng15。由于我的应用程序还链接了链接 libpng3 的 DI-GUY,因此这两个版本发生冲突。 “冲突”是指链接器 (ldd) 选择 libpng3 而不是 libpng15。
如果我查看 ldd 输出,则会列出 libpng15 和 libpng3。顺序如下:
libpng.so.3 => ../lib/libpng.so.3 (0x00007f4bccdff000)
libpng15.so.15 => ../lib/libpng15.so.15 (0x00007f4bc5d1b000)
在 CMake 中,我确保我专门针对 15 进行链接:
add_library(PNG::Shared SHARED IMPORTED)
set_target_properties(PNG::Shared PROPERTIES
IMPORTED_LOCATION ${_IMPORT_PREFIX}/lib/libpng15.so.15.4.0
INTERFACE_INCLUDE_DIRECTORIES ${_IMPORT_PREFIX}/include
INTERFACE_LINK_LIBRARIES z
)
据我了解,应用程序应该采用 libpng15,但由于 libpng.so.3 在 ldd 中比 15 版本更高级,因此链接器选择 libpng.so.3。
如何强制我的应用程序使用 libpng15.so.15,而 DI-GUY 库将使用 libpng.so.3。因为我无法重新编译 DI-GUY,所以我坚持 libpng.so.3 也被链接,但它不应该与 15 版本混淆......
我不明白为什么甚至考虑 libpng.so.3,因为我明确链接到 libpng15.so.15.4.0
【问题讨论】:
-
With "clash" I mean that the linker (ldd) picks the libpng3 instead of libpng15.- 不,即使libpng.so.3和libpng15.so.15链接到同一个可执行文件,链接器也会正确分离它们。问题是这两个库版本可能会有相同的符号(函数、变量),因此在运行时可能会选择错误的符号。这就是为什么应不惜一切代价避免与同一库的两个版本链接的原因。否则你可能会突然崩溃。 -
我的应用程序一开始就抱怨,我用 libpng15.so.15 编译但用 libpng.so.3 运行,所以它知道它应该使用 libpng15.so.15。您是否建议如果首先链接一个完全不同的lib“X”,并且具有与libpng相同的符号,那么将采用X而不是libpng?在我看来,这将是一场灾难,还是仅针对具有不同版本的相同库?如果是,链接器如何知道 2 个库是相同的,只是版本不同,而不是偶然有相同的符号?
-
“我的应用程序一开始就抱怨,我使用 libpng15.so.15 编译但使用 libpng.so.3 运行,所以它确实知道应该使用 libpng15.so.15。” - 您的应用程序似乎使用了一些请求库版本的 libpng 函数。但是链接器将 libpng3 函数解析为 libpng15(反之亦然)。 “链接器如何知道 2 个库相同只是版本不同” - 链接器看到
libpng.so.3和libpng15.so.15:不同的名称 - 不同的库。它不会将它们视为相同的库,而是具有不同的版本。