当前位置: 首页 > 面试题库 >

链接库的多个版本

阎智
2023-03-14
问题内容

我有一个与第三方供应商VENDOR1的库X版本libfoo静态链接的应用程序。它还与来自第三方供应商VENDOR2的动态(共享)库libbar链接,该库静态链接了VENDOR1的libfoo版本Y。

因此libbar.so包含libfoo.a的Y版本,而我的可执行文件包含libfoo.x的X版本。libbar仅在内部使用libfoo,并且没有从我的应用程序传递到libbar的libfoo对象。

在构建时没有错误,但在运行时应用段错误。原因似乎是版本X使用了与版本Y不同大小的结构,并且运行时链接程序似乎混淆了哪个被哪个使用。

VENDOR1和VENDOR2均为封闭源,因此我无法重建它们。

有没有一种方法可以构建/链接我的应用程序,使其始终解析为版本X,而libbar始终解析为版本Y,并且两者永不混合?


问题答案:

感谢您的所有回复。我有一个似乎有效的解决方案。这是一个带有示例的详细问题。

在main.c中,我们有:

#include <stdio.h>

extern int foo();

int bar()
{
    printf("bar in main.c called\n");
    return 0;
}

int main()
{
    printf("result from foo is %d\n", foo());
    printf("result from bar is %d\n", bar());
}

在foo.c中,我们有:

extern int bar();

int foo()
{
    int x = bar();
    return x;
}

在bar.c中,我们有:

#include <stdio.h>

int bar()
{
    printf("bar in bar.c called\n");
    return 2;
}

编译bar.c和foo.c:

$ gcc -fPIC -c bar.c
$ gcc -fPIC -c foo.c

将bar.o添加到静态库中:

$ ar r libbar.a bar.o

现在使用foo.o创建一个共享库,并与静态libbar.a链接

$ gcc -shared -o libfoo.so foo.o -L. -lbar

编译main.c并与共享库libfoo.so链接

$ gcc -o main main.c -L. -lfoo

设置LD_LIBRARY_PATH以找到libfoo.so并运行main:

$ setenv LD_LIBRARY_PATH `pwd`
$ ./main
bar in main.c called
result from foo is 0
bar in main.c called
result from bar is 0

注意,将调用main.c中的bar版本,而不是链接到共享库中的版本。

在main2.c中,我们有:

#include <stdio.h>
#include <dlfcn.h>


int bar()
{
    printf("bar in main2.c called\n");
    return 0;
}

int main()
{
    int x;
    int (*foo)();
    void *handle = dlopen("libfoo.so", RTLD_GLOBAL|RTLD_LAZY);
    foo = dlsym(handle, "foo");
    printf("result from foo is %d\n", foo());
    printf("result from bar is %d\n", bar());
}

编译并运行main2.c(注意,我们不需要显式链接libfoo.so):

$ gcc -o main2 main2.c -ldl
$ ./main2
bar in bar.c called
result from foo is 2
bar in main2.c called
result from bar is 0

现在,共享库中共享库调用栏中的foo和main.c中的主调用栏中

我不认为这种行为是直观的,使用dlopen / dlsym的工作量更大,但这确实解决了我的问题。

再次感谢您的评论。



 类似资料:
  • 问题内容: 我正在寻找一种可以链接多个HTTP请求的良好模式。我想使用Swift,最好使用Alamofire。 举例来说,我要执行以下操作: 发出PUT请求 发出GET请求 用数据重新加载表 承诺的概念似乎很适合此目的。如果我可以执行以下操作,则PromiseKit可能是一个不错的选择: 但这是不可能的,或者至少我不知道。 如何在不嵌套多个方法的情况下实现此功能? 我是iOS的新手,所以也许我缺少

  • 问题内容: 后续问题应用程序在运行时如何解析为共享库的不同版本?,我想知道如何在链接命令行上指定要使用哪个版本的库? 假设我有 指定库与可执行文件链接的通常方法不会显示要使用的版本。此外,很可能要链接到最新版本。因此,通常的线路在大多数情况下都可以正常工作。 使用该库的版本1 进行链接的命令行是什么? 问题答案: 链接器也可以接受文件名 来自: -l namespec --library = na

  • 问题内容: 安装新的构建机器后,我发现它带有标准C ++库的6.0.10 但是,我们的许多目标计算机仍使用旧版本的libstdc ++,例如: 显然,在最后两个0.0.1中,ABI发生了变化,因为尝试运行程序会导致 我尝试明确安装旧版本的gcc,但没有帮助。升级目标计算机是我无法控制的,因此不是一种选择。使我的构建在具有较旧libstdc ++的计算机上工作的最佳方法是什么? 我在apt-cach

  • 问题内容: 我需要链接来自Google Maps API的一些API请求,而我正在尝试使用Axios来实现。 这是第一个请求,它在componentWillMount()中 这是第二个请求: 然后,我们有第三个请求,这取决于前两个请求是否完成: 如何链接这三个电话,以便第三个电话发生在前两个电话之后? 问题答案: 首先,不确定是否要在其中执行此操作,最好将其插入并具有一些默认状态,这些状态一旦完成

  • 问题内容: 我正在编译一些在Debian Linux系统上使用libcurl的代码。我的开发机正在运行Debian 5,但我也希望二进制文件也可以在较旧的Debian 4系统上使用。 我发现如果指定 -lcurl ,它将链接到libcurl.so.4,但是Debian 4系统仅具有libcurl.so.3 有什么方法可以告诉GCC链接到libcurl.so.3(在Debian 4和5中都存在)还是

  • 问题内容: 我有三个表:,,和。 该表包含类别的名称和其类别的ID 。 在包含两列:为这篇文章的ID和该职位的类别的ID。 该表包含有关后多列-如,等 我在网址中有一个名为parent_id的变量,它对应于一个类别。我想列出所有属于parent_id值类别的帖子(而不是类别)。 例如,假设parent_id值为5。每个帖子可能属于ID为20的类别,但该类别属于父类别(其ID为5)。我想列出所有属于