Why Would It Be Impossible to Fully Statically Link an Application

Why would it be impossible to fully statically link an application?

Function calls that need access to NSS or iconv need access will open other libs dynamically, since NSS needs plugins to work (the helper modules like pam_unix.so). When the NSS system dlopens these modules, there will be two conflicting versions of glibc - the one your program brought with it (statically compiled in), and the one dlopen()ed by NSS dependencies. Shit will happen.

This is why you can't build static programs using getpwnam_r and a few other functions.

Why is statically linking glibc discouraged?

The reasons given in other answers are correct, but they are not the most important reason.

The most important reason why glibc should not be statically linked, is that it makes extensive internal use of dlopen, to load NSS (Name Service Switch) modules and iconv conversions. The modules themselves refer to C library functions. If the main program is dynamically linked with the C library, that's no problem. But if the main program is statically linked with the C library, dlopen has to go load a second copy of the C library to satisfy the modules' load requirements.

This means your "statically linked" program still needs a copy of libc.so.6 to be present on the file system, plus the NSS or iconv or whatever modules themselves, plus other dynamic libraries that the modules might need, like ld-linux.so.2, libresolv.so.2, etc. This is not what people usually want when they statically link programs.

It also means the statically linked program has two copies of the C library in its address space, and they might fight over whose stdout buffer is to be used, who gets to call sbrk with a nonzero argument, that sort of thing. There is a bunch of defensive logic inside glibc to try to make this work, but it's never been guaranteed to work.

You might think your program doesn't need to worry about this because it doesn't ever call getaddrinfo or iconv, but locale support uses iconv internally, which means any stdio.h function might trigger a call to dlopen, and you don't control this, the user's environment variable settings do.

And if your program does call iconv, for example, then things get even worse, especially when a “statically linked” executable is built on one distro, and then copied to another. The iconv modules are sometimes located in different places on different distros, so an executable that was built, say, on a Red Hat distro may fail to run properly on a Debian one, which is exactly the opposite of what people want from statically linked executables.

Why isn't static linking used more?

There are three big reasons:

  1. GNU libc doesn't support static linkage to itself, because it makes extensive internal use of dlopen. (This means that static linkage to anything else is less worthwhile, because you can't get a totally static binary without replacing the C library.)
  2. Distributions don't support static linkage to anything else, because it increases the amount of work they have to do when a library has a security vulnerability.
  3. Distributions have no interest whatsoever in distribution-agnostic binaries. They want to get the source and build it themselves.

You should also keep in mind that the Linux-not-Android software ecology is entirely source-based. If you are shipping binaries and you're not a distribution vendor you are Doing It Wrong.

When wouldn't you use -static-link-runtime-shared-libraries?

If you have several applications for one project making the framework available as an RSL enables the other applications to load it from cache (it has been loaded there by the first app) and save bandwidth and time. If you set static linking to true, every application will contain the framework classes increasing your file sizes.

If you have only one application .swf, linking framework as an RSL can save bandwidth on updates - if only the main .swf changes, you can load it again bypassing the cache but load all the cached .swcs.

Unable to link to static boost library using VS2012 while dynamic linking works fine

Invoke b2 with the following parameters:

link=static runtime-link=static

Note that there are no hyphens before link and runtime-link.

Why are static and dynamic linkable libraries different?

Static libraries are true libraries in the sense that they contain a library of object files. Each object file is often created from a single source file and contains machine code as well as information about data required for the code. During the link step the linker will pick the necessary object files and combine them into an executable.

One important part of machine code is that jumps, calls and data pointers will have to contain real memory addresses. However, if an object file needs to call another function in another object file it can only refer to that function using a symbol. When the linker combines the object files into executable code the symbol references are resolved and turned into real memory addresses.

A dynamic library is executable code that can be loaded into the memory and executed straight away. On some operating systems there may be an additional step where the code is rebased by moving the executable code to another location and this requires all absolute addresses within the code to be shifted by a fixed amount. This operation is still much faster than combining object files and resolving symbols done by the linker.

To sum it up:

  • Static libraries contain pieces of executable code that uses symbols to refer to other pieces of executable code
  • Dynamic libraries (and executables) contain executable code now placed at fixed locations enabling the symbols to be replaced with real memory addresses

If you've ever tried to link a reasonably sized project you will have noticed that it takes a non-trivial amount of time, probably longer than you would like to wait to start an application. That sort of explains why you can't execute static libraries. And dynamic libraries have been optimized and stripped to not contain anything except executable code which makes them unsuitable for use as static libraries.

Statically link openssl in Visual C++ malloc warning

C and C++ memory management is implemented in the CRT (C Runtime Library). Each physical copy of the CRT mapped into a process (either statically compiled into a module, or referenced DLL) uses a distinct heap. Memory allocations and deallocations must be performed on the same heap, i.e. the same physical CRT copy (see Potential Errors Passing CRT Objects Across DLL Boundaries for more details).

In your specific scenario you need to make sure to do the following:

  • Dynamically link your application against the OpenSSL DLLs.
  • Dynamically link your application against the CRT.
  • Verify that both your application and the OpenSSL DLLs link against identical versions of the CRT (version and configuration).

While it is possible to statically link against OpenSSL, if you can ensure that your final binary contains a single CRT implementation and doesn't (directly or indirectly) dynamically link against the CRT as well. This is difficult to maintain, and breaks as soon as you link against a library, that doesn't provide a static library.



Related Topics



Leave a reply



Submit