views:

474

answers:

4

I want to preface this with the important notice that I am not a C/C++ programmer, and know very little about how linkage of libraries works in C.

Our code uses libstdc++.so.6 (gcc 3.4, i think). We have third-party precompiled (closed source) libraries that use libstdc++.so.5 (gcc 2.something or 3.2, i think). This is on linux. We have both a .a and .so version of the third party lib.

Is it possible to build our app with the 3rd party libs? How? Is it possible to build/run our app without having libstdc++.so.5 installed our our machines, how?

If I've forgotten some critical information, please let me know - I hardly know whats relevant with this stuff. I realize that a complete answer probably won't be possible; I'm really looking for direction and guidance. Static link this, dynamic that, rebuild that, prebuild so-and-so, switch to version x, or symlink the quizdoodle, etc.

Update:

We tried using dlopen with RTLD_LOCAL to isolate the 3rd party library from the rest of our app. This seems to have mostly worked, however, we are left with large memory leaks for unknown reasons. We suspect that, when we call dlopen, the third party library pulls in symbols like malloc from the already loaded .so.6, and things get muddled up.

For giggles, we tried putting the third-party library into LD_PRELOAD, then ran our app, and the memory leaks seems to completely disappear.

+1  A: 

While it is easy to link both libstdc++.so.6 and libstdc++.so.5 to your application at the same time, its behavior will pretty much be undefined, because symbols are taken from either library basically by chance.

Best way to success IMO is to build an own application around your 3rd party lib on an old system (which is using a compatible gcc like, for instance, gcc 3.3), and let it communicate with your main application via IPC (eg. shared memory). This way, no

If you don't want to keep libstdc++.so.5 on your target system, then that's easy: use gcc's -static flag to link libstdc++.a to your wrapper application.

Martin
I found a similar question, and one of the responses implies that, through some sort of dynamic linking magic, using both is possible without problems. Is that true, or misinformation?http://stackoverflow.com/questions/728858/can-an-application-depend-on-two-different-versions-of-libstdc/728885#728885
Richard Levasseur
+4  A: 

Ask your vendor for a newer version of the library that uses something not horribly out of date. Failing that, you could see if your new application still works with the older version of the library and if necessary port it back. Trying to have two different versions of the same library is asking for pain and I don't think you'll find an acceptable solution.

Steven Schlansker
The vendor is very resistant against upgrading their library (we've been arguing for weeks now). The app can't be backported to .so.5
Richard Levasseur
ditch the vendor ...
stefanB
+3  A: 

You may try to build a wrapper library around your 3rd party library: use the static version of that library + link it with the static standard library (-static-libgcc - make sure you pick up a proper version via -L). The important thing to do is to close this wrapper library properly, i.e only symbols from the original 3rd party library should be exported, everything else should be hidden. This way you wrapper library will expose all needed symbols for your application and encapsulate standard stuff inside. Note it is not guaranteed to work especially if some memory operations are shared between your code and 3rd party code (e.g. you allocate memory in your code and deallocate in 3rd party)... in such case the only option can be to keep this 3rd party lib in a different process space.

I don't think the dynamic option mentioned above would work because you will get exactly same problem - just later.

In general it is better not to mix binaries with different run-times in the same process space. It is almost always a recipe for disaster.

pobedim
Can you explain how to properly hide the symbols, and what you're saying about the memory operations? We tried wrapping the 3rd party lib in functions that would use dlopen(lib, RTLD_LOCAL) to load the 3rd party lib. This kept our code from linking in .so.5, but, we suspected, that the 3rd party code was picking up symbols (like malloc) from the already loaded .so.6 (loaded by our code), and was causing memory leaks. We tried using LD_PRELOAD to loud the 3rdparty lib first, and the memory leaks pretty much went away.
Richard Levasseur
And we _do_ allocate in on our side, and the 3rd party lib deallocates. e.g.:ThirdPartyStruct * foo = malloc(...);ThirdPartyApiCall(foo);ThirdPartyFreeStruct(foo); - Are you saying that just plain won't be possible if we're using .6, and its using .5? What if we used .5 with our wrapper functions, and did all allocation/deallocation through the wrapper lib?
Richard Levasseur
When allocation/deallocaiton is performed in different standard libraries you cannot be sure that they do this in same way... you simply do not knoww. I can't say if it is a real problem on Linux but on Windows definitely it is: if you are using different runtimes in your libraries and do allocation in one and deallocation in other you will get a run-time exception. I wouldn't even consider mixing different standard libraries in your case, even if it works on this particular platform with these particular runtimes you cannot be sure it will work when you move to a new version of libstd...
pobedim
Something to read about binary compatibility: http://gcc.gnu.org/onlinedocs/gcc/Compatibility.html
pobedim
pobedim
A: 

While one of the approaches given so far may work, I think it is safer to say that you can't do this directly a reliable fashion. If you write a wrapper using entirely C-based API's (only C-compatible structures, memory managed by malloc/free, etc.), then you might be able to use pobedim's solution. If you need to exchange C++ structures, however, it is not safe as, even if you could make the link happen, different standard libraries implementations would be used on the same objects. Also, the C++ ABI may not be compatible between .5- and .6-based code bases (I don't remember for sure how the major Gnu C++ ABI change happened a few years ago related to standard library sonames).

I think the safest approach to solving this is to use a multiprocess approach with some kind of IPC between your application and a resource/computing server process built on the library in question. You could use CORBA, D-Bus, Sun RPC, or some ad-hoc protocol over pipes or sockets to do the job. I've done this when trying to use closed-source 32-bit code in 64-bit apps, and it works well enough. You will see a performance hit, but you will also completely sidestep the problems inherent in trying to mix C++ runtimes in a single process.

Michael E