1

This question has been asked a few times already, but I observe that it always refers to Windows. Which makes sense, given that MSVC fails with the following error:

error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.obj

And it seems to me that on Linux, it does not fail at build time.

Answers mention different C++ runtime between the build types and not sharing CRT resources between such libraries. Still, it is not clear to me how different that behavior is in Linux/Windows and with shared/static libraries.

I would like to understand this better. Questions could be:

  1. Is it different between Windows and Linux?
  2. If it is also undefined behavior in Linux, how come it doesn't fail at build time?
  3. Is it different between static and shared libraries?
  4. Does my Linux package manager download debug versions of all the dev packages? Looking into usr/lib/, I can't seem to find both release and debug libraries there...
JonasVautherin
  • 7,297
  • 6
  • 49
  • 95
  • If the `_ITERATOR_DEBUG_LEVEL` is different, then the issue starts off at the compilation phase, not the link/library phase – PaulMcKenzie Apr 19 '19 at 12:53
  • What's the consequence of that statement? Does it mean that shared libraries should not be an issue then? – JonasVautherin Apr 19 '19 at 13:10
  • 1
    For Windows, when ITERATOR_DEBUG_LEVEL is invoked, the compiler adds/removes code from various classes (such as the STL classes). So when you link with a differing debug level, you are possibly linking in two or more different versions of the same class, thus the error. – PaulMcKenzie Apr 19 '19 at 13:13
  • 1
    Right. So the error is raised at compile time, and if it did not it would result in undefined behavior at runtime, right? Meaning that linking is never an issue, and both static and shared libraries have that issue in Windows. Correct? – JonasVautherin Apr 19 '19 at 13:21
  • Yes, undefined behavior will result if the class internals have changed between modules. – PaulMcKenzie Apr 19 '19 at 16:14

2 Answers2

5

Yes Linux and Windows are different. I cannot tell much for Windows, but with Linux toolchains we don't really have a split Debug vs Release build.

What we have is several options:

  • which optimizations are enabled?
  • should debugging symbols be emitted?
  • some other less relevant stuff.

What build toolchain refer as "Release" or "Debug" is just a set of options. for instance, CMake's min-size release build uses -Os -DNDEBUG, while CMake's debug release uses -g. Distributions also add additional options when they package stuff.

But other than those options, the ABI is the same, so those are all compatible (except for options specifically marked[*] - but those are not used in typical builds). So it doesn't matter. You can mix "debug" or "release" objets, it will work.

As for 4), the way a lot of distributions do it is they build with split debugging symbols. That means debugging information is emitted in a separate file, and typically packaged independently. For instance:

ii  libc6:amd64       2.27-3ubuntu1  GNU C Library: Shared libraries
ii  libc6-dbg:amd64   2.27-3ubuntu1  GNU C Library: detached debugging symbols

Second package is normally not installed. I installed it manually to step through libc6 with full debug info.


[*] For an exemple, check out GCC code generation options. You'll see those that generate incompatible objects have a warning on them.

spectras
  • 13,105
  • 2
  • 31
  • 53
2

On Windows one can refer to different runtime libraries in a single process. This was always possible on Windows but it is still not possible on LINUX.

Importing something from a (runtime-)dll (on Windows) is done not only by name of the symbol but also by name of the dll.

Thus on windows one imports by pair of dll-name and symbol name. On LINUX one imports only by symbol name.

This creates gigantic problems (on LINUX) if one attempts to have binaries from different vendors work together in a single process.

This situation is already baked into the system. On Windows different runtimes are able to separately allocate their HEAP area. On LINUX one has a single area which cannot be shared by multiple runtimes.

I'm very curious that this problem is seems to be widely unknown and widely unappreciated. Software vendors for LINUX are bending over backwards in order to enable their customers to load shared libraries build with different compilers. This usually involves linking the runtime library statically and I'm not certain if it is supported at all.

compare man 2 brk with windows Heap functions

Frank Puck
  • 467
  • 1
  • 11
  • Note: the counterpart of windows heap functions is not brk but mmap, using anonymous mappings — and no this does not create problems on Linux as the support libraries are fully backwards compatible. Just be sure the most recent is the one loaded and you are good. – spectras Jun 06 '23 at 20:43
  • @spectras This might be very well true, but is not really helpful, unless you're able to tell me, how multiple shared libraries (exporting & importing C interfaces) compiled with different compilers ought to work inside a single process. – Frank Puck Jun 07 '23 at 20:42
  • > the Linux C ABI is standardized (C++ is another matter). Do you have a specific problem or is this entirely hypothetical? This is something we routinely do as we sell plugins for software solutions of other vendors, and it just works. – spectras Jun 07 '23 at 22:50