Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Based on the discussion around this question. I'd like to know how .so files/the ELF format/the gcc toolchain avoid problems passing classes defined purely in header files (like the std library). According to Jan in that answer, the dynamic linker/loader only picks one version of such a class to load if its defined in two .so files. So if two .so files have two definitions, perhaps with different compiler options/etc, the dynamic linker can pick one to use.

Is this correct? How does this work with inlining? For example, MSVC inlines templates aggressively. This makes the solution I describe above untenable for dlls. Does Gcc never inline header-only templates like the std library as MSVC does? If so wouldn't that make the functionality of ELF described above ineffective in these cases?

share|improve this question

What the ELF linker does is that it ensures that static and dynamic linker produce the same result. So using shared objects does not create any new problems. You can create some if you use of non-default visibility or version or linker scripts, but you obviously wouldn't do that if it isn't safe in that particular case.

Now if you use incompatible sets of compiler flags for building different objects, whether shared or static, in one application, you will have problems. You can have two kinds of problems:

  • The flags are so incompatible that calling convention, structure layout or some other such parameter is different between the modules. Obviously the only solution is to know which compiler options always have to remain set to the platform defaults.

  • The flags modify content of the headers and thus violate one definition rule. Authors of standard libraries, at least the open-source ones, know well how to avoid breaking compatibility between objects. But if you have some special library who's author were not careful, you can get in trouble and will have to make sure the compilation flags are compatible.

In Linux I've not seen these problems happen. Everybody knows not to touch the compiler flags that could break anything and there are no special incompatible versions for debug or such (gcc can emit debug information in optimizing build, so you normally just get unstripped version of the same object or lately even just the debug information for the normal object split out to separate file).

This is different from Windows, where:

  • Due to the way shared libraries need explicit export and import there will not merge symbols (like template instances or class impedimenta) generated into different shared libraries.
  • Have separate debug and release runtimes that differ in both the shared library used and lot of preprocessor magic. It means that you can't link your debug build to libraries built with the release version, so every library needs to ship debug and release variant. And often variant for static and dynamic linking. And despite all this trouble I don't think the debug support on Windows is better; e.g. Linux libc has hooks for replacing allocator (with debug one) which is always gross hack on Windows and Linux has great tools like Valgrind.
  • Have lots of compiler flags that get flipped for various compatibility reasons, causing more complications. It has to be said that Microsoft is in more difficult position here. Since they cater primarily for the closed-source programmers, they have to assume things can't be recompiled and have to provide various compatibility kludges to keep things working. Linux people just assume things can be recompiled and do a breaking change when things get too complicated, like the switch to ELF format was; The ELF format was created between 1997 and 1999, while Windows objects are still backward compatible to the old Windows 3.1 ones. At the cost of all the mess.
share|improve this answer

I'm not sure I understand. If you build parts of your program with different incompatible flags, it's not a .so or .dll problems, the same problems will appear with static libraries as well.

First note that I stopped programming for Windows in 94. So nearly all my understanding about Windows behavior comes from the net and discussions with colleagues working on Windows and may be outdated, misremembered badly understood facts.

  • It is customary on Windows to include the standard library in .DLL. That's not the case on Unix (and I get it isn't mandatory on Windows).

  • Default symbol resolution on Windows prefer the DLL, on Unix it will be the normal search (in both, you may changing it).

  • It's considered bad practice on Unix to make debug libraries which aren't substitutable for the optimized one. Yes this limit the instrumentation which can be done, but it make a lot of thing easier. We may do special instrumented libraries which need a total recompilation when they are worthwhile, but it's not the case for routine debug builds. My understanding is that MSC++ compiler ships with some libraries which aren't substitutable if you compile user code in debug or optimized (I've heard horror stories with #defining new for instance, which seems to me a very bad idea even for special instrumented builds). Nothing of Windows forces you to do that bad practice (but if the standard C++ library is in that case, you probably have to use a saner standard library).

share|improve this answer
On Linux (other Unices may differ) standard library is always .so and it can be considered mandatory. It's required by packaging guidelines of most distributions and for legal requirement for closed-source applications, since the standard libraries are LGPL. – Jan Hudec Nov 22 '12 at 6:48

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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