Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
256 views
in Technique[技术] by (71.8m points)

c++ - Linking with multiple versions of a library

I have an application that statically links with version X of a library, libfoo, from thirdparty vendor, VENDOR1. It also links with a dynamic (shared) library, libbar, from a different thirdparty vendor, VENDOR2, that statically links version Y of libfoo from VENDOR1.

So libbar.so contains version Y of libfoo.a and my executable contains version X of libfoo.a libbar only uses libfoo internally and there are no libfoo objects passed from my app to libbar.

There are no errors at build time but at runtime the app seg faults. The reason seems to be that version X uses structures that have a different size they version Y and the runtime linker seems to be mixing up which get used by which.

Both VENDOR1 & VENDOR2 are closed source so I cannot rebuild them.

Is there a way to build/link my app such that it always resolves to version X and libbar alway resolves to version Y and the two never mix?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Thanks for all the responses. I have a solution that seem to be working. Here's the problem in detail with an example.

In main.c we have:

#include <stdio.h>

extern int foo();

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

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

In foo.c we have:

extern int bar();

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

In bar.c we have:

#include <stdio.h>

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

Compile bar.c and foo.c:

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

Add bar.o to a static library:

$ ar r libbar.a bar.o

Now create a shared library using foo.o and link with static libbar.a

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

Compile main.c and link with shared library libfoo.so

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

Set LD_LIBRARY_PATH to find libfoo.so and run 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

Notice that the version of bar in main.c is called, not the version linked into the shared library.

In main2.c we have:

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


int bar()
{
    printf("bar in main2.c called
");
    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
", foo());
    printf("result from bar is %d
", bar());
}

Compile and run main2.c (notice we dont need to explicitly link with 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

Now foo in the shared library calls bar in the shared library and main calls bar in main.c

I don't think this behaviour is intuitive and it is more work to use dlopen/dlsym, but it does resolve my problem.

Thanks again for the comments.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...