1

Currently I am trying to implement an ELF shared library, built with -static-libstdc++ and -static-libgcc options. This shared library MUST be built with C++11 and it has some legacy code, besides, it has a very specific design.

If some application links this shared library, their C++ utilities MUST NOT interfere with each other. For example, std::cout-related, and hence, std::ios_base::Init::Init() (_ZNSt8ios_base4InitC1Ev), are awaited to be present in two independent implementations, one static for this specific shared library, and another shared one for the application and it's other shared libraries. However, LD_DEBUG=all usage shows that there this specific shared library's C++ utility symbols, like std::ios_base::Init::Init(), get bound to the symbols, defined in libstdc++, which I try to avoid...

Can such logic be implemented or at least worked around somehow? In any case, I DO NEED separate C++ utility. Thanks in advance!

1
  • A static library is really nothing more than an archive of object files. When you link with a static library, its like linking with the individual object files. When you link with a static library, it becomes an integral part of your executable or shared library. Unfortunately that means global data in your library will clash with global data from the process your library is running with. Besides that, a library really shouldn't be using global state, including std::cout. If the library needs to use a stream, let the host process pass it in using some kind of initialization function. Commented Jun 27, 2023 at 16:13

1 Answer 1

2

Currently I am trying to implement an ELF shared library, built with -static-libstdc++ and -static-libgcc options.

Your best bet is to not do that -- link your library "normally" (so it depends on libstdc++.so.6 and libgcc_s.so.1), and most of your problems would disappear. (See also http://xyproblem.info -- why do you want to link libstdc++ statically?)

However, LD_DEBUG=all usage shows that there this specific shared library's C++ utility symbols, like std::ios_base::Init::Init(), get bound to the symbols, defined in libstdc++

This statement is meaningless when you have two copies of libstdc++ -- one inside your library, and one "outside" (presumably libstdc++.so.6).

What you probably mean is that references to std::ios_base::Init::Init() from your library get bound to definitions inside libstdc++.so.6.

You can avoid this by making all symbols inside your library hidden, and only exposing the "official" interface from it, using linker script. See this answer.

Note:

  • Controlling the ABI of a C++ shared library is much harder than for a pure-C one
  • If you "hide" libstdc++ inside your shared library, and pass C++ objects through the interface (e.g. a std::string or std::map), you can expect all kinds of ~impossible to debug issues due to ABI incompatibility between the "hidden" libstdc++.a and the external libstdc++.so.6.
1
  • Wow, this is exactly what I needed! Thank you ever so much! Using the linker script has helped, now all those externally visible C++ symbols are hidden, as intended. Note this is fairly abnormal programming. Related build options are: -shared -fPIC -static-libgcc -static-libstdc++ -Wl,--version-script=libfoo.version. Commented Jun 30, 2023 at 16:02

Not the answer you're looking for? Browse other questions tagged or ask your own question.