2

This is something I've just blindly accepted and followed as "the way it is". I'm trying to gain a deeper understanding of the "why" behind it.

  • static library LibA - utulizes some C runtime calls
  • static library LibB - utilizes some C runtime calls
  • executable App - utilizes LibA, LibB, and some C runtime calls

It is pretty well documented here and a bunch of other places that all modules passed to a given invocation of the linker must have been compiled with the same run-time library compiler option.

If all symbol resolution is performed during the final link for App as discussed here and here, why is this the case? Why do LibA and LibB even need to specify a specific runtime library to use when they build? Shouldn't the C runtime calls they use just resolve against whatever runtime App specifies for its link?

Is this an issue in other C development environments or is it specific to Visual Studio?

Community
  • 1
  • 1
ribram
  • 2,392
  • 1
  • 18
  • 20
  • 2
    The CRT just isn't very compatible with the notion of modules, it has a lot of global state. A variable like errno is a good example. To enable sharing that state between the EXE and DLLs, the definition of errno needs to be hacked to turn into a function call so the one-and-only shared value can be obtained. Triggered by /MD. Trying to link an .obj that refers to errno with another that refers to _errno() can't work. Not entirely accurate but representative for the problem. – Hans Passant Apr 04 '12 at 16:03

1 Answers1

0

As Hans Passant mentioned in his comment, there are some global state items that have to change between a DLLs runtime and a static link runtime. Even worse than his example is when the size of a type changes based upon which runtime created it. However, there are a few more reasons:

Debug vs Release:
The debug runtimes will place guard bytes surrounding dynamically allocated memory. This allows their memory allocation and freeing code to do extra checks to help you find memory problems such as double-frees and writing outside your allocated buffers. The release runtimes don't don't use the extra checks in favor of optimization. Therefore, if memory is allocated with one and freed with another, you may get unpredictable results.

DLL vs static linkage:
In Windows, the rule of thumb is that you must free memory in the same module which you allocated it. In other words, if you allocated memory in msvcrt.dll, you must also free it there. Therefore, if some parts of an application link to a static runtime and some link to a runtime DLL, this rule may be violated. When this happens, you can also get unpredictable results including exceptions.

Multithread vs Singlethread:
The potential for conflicts between these 2 runtime types should be obvious. The single threaded version isn't thread safe, so mixing it with something expecting thread safety will make for interesting debugging later. This distinction is largely only present in the older MS compilers since the only option is multithreaded in newer releases.

See also this similar question: Mixing Static Libraries of C Code built from different versions of Visual Studio 2002 and later

Community
  • 1
  • 1
Patrick W
  • 317
  • 1
  • 13