C++ 在Linux中,共享库使用来自主程序的函数,而不是其他共享库

C++ 在Linux中,共享库使用来自主程序的函数,而不是其他共享库,c++,c,linux,shared-libraries,C++,C,Linux,Shared Libraries,我正在构建一个从应用程序加载的共享库(我无法控制)。我的库使用其他共享库,而这些共享库又使用其他共享库,虽然复杂但并不罕见 问题在于,主应用程序的函数存在于链中较低的一个库中,更具体地说,是openLDAP依次使用openSSL函数: Main app->My library->openLDAP libraries->openSSL libraries 我的猜测是,主应用程序正在通过静态链接或简单的源代码复制/粘贴来实现openSSL 我的问题是:我可以控制openLDAP从

我正在构建一个从应用程序加载的共享库(我无法控制)。我的库使用其他共享库,而这些共享库又使用其他共享库,虽然复杂但并不罕见

问题在于,主应用程序的函数存在于链中较低的一个库中,更具体地说,是
openLDAP
依次使用
openSSL
函数:

Main app->My library->openLDAP libraries->openSSL libraries
我的猜测是,主应用程序正在通过静态链接或简单的源代码复制/粘贴来实现
openSSL

我的问题是:我可以控制
openLDAP
从我的库中使用哪些函数,还是必须使用到
openSSL
的静态链接重新编译
openLDAP


由于由于安全问题,
openSSL
经常更新,如果不需要的话,我不想要它的静态副本。当它是大多数发行包的一部分时,为什么要重新发行一个专有的
openLDAP

现在,您拥有的是可执行文件,它覆盖了系统默认选择的OpenSSL库。这样做是在可执行文件的权限范围内的,您不能真正阻止它

在库中静态链接OpenSSL也可能不是一个真正的解决方案。首先,如果可执行文件的真正用途是使用不同的版本,该怎么办?另一方面,如果OpenSSL有一些全局变量呢?现在,您将在同一个过程中获得库的两个副本,这不是一个好主意,可能会导致bug

对我来说,Linux上最好的答案是不要认为这类问题是一个问题。如果可执行文件加载了错误版本的OpenSSL,那不是您的库的错。您最多可以检查加载了哪个版本,如果由于某种原因已知该版本与库不兼容,则可以拒绝运行该版本

我的猜测是,主应用程序也在实现openSSL 通过静态链接或源代码的简单复制/粘贴

这是错误的事情。如果应用程序开发人员一意孤行,那么你什么都做不了

应用程序开发人员应该看到您的库依赖于OpenSSL库(使用ldd命令),然后他不应该再次静态链接
OpenSSL或复制粘贴其代码。


如果OpenSSL中的某些函数不会产生任何混乱,并且它们可以像任何java类的任何静态方法一样使用,那么只有应用程序开发人员才应该冒险在应用程序中实现这些代码

解决方案是在dlopen中使用RTLD_DEEPBIND(3):

RTLD_DEEPBIND(自glibc 2.3.4起)

将此库中符号的查找范围放置在 全球范围。这意味着自包含库将使用其 拥有符号优先于具有相同名称的全局符号 包含在已加载的库中。这面旗子不是 POSIX.1-2001中规定


这可能不是最好的解决方案,但当进程由封闭源代码软件创建时,它可以在这种情况下工作。

我使用Mozilla NSS而不是openSSL构建openLDAP。这样我就不会做任何尴尬的事情,也不会试图解决别人的错误。