5

I've been bitten for the n-th time now by a library mismatch between a build and deployment environment. The build environment had libruby.so.2.0 and the deployment environment had libruby.a. One ruby was built with RVM, the other was built with ruby-build. The reason I ran into a problem was because zookeeper was compiled in a build environment that had the shared library but the deployment environment only had the static library.

In all the years I've been writing application code I have never once wished that the binaries I was using where linked against shared objects. What is the reason the dichotomy persists to this day on modern operating systems?

  • 1
    I have a number of very small applications that take seconds to download and deploy. They depend on installed libraries that are loaded dynamically and some of those libraries are huge. Run-time version checking solves the issues you are seeing. – BobDalgleish Jun 6 '14 at 0:48
7

Static

With a statically linked application, everything that you need to run the application is part of the application itself. It depends on nothing else.

If there is a fatal error in a dynamically linked library, it doesn't 'care'.

If the dynamically linked version of a library it uses isn't there (someone accidentally removed /lib on a unix system?) it doesn't care.

It requires no additional installs of libraries to run on any binary compatible platform. You download the app and you can run it.

There is an entire directory of statically linked applications on every unix system in /sbin that are guaranteed to always work even if significant parts of the system are otherwise broken or missing. reboot? halt? ifconfig? mount? fsck? ping? Those are likely all in /sbin so that even if the libraries are missing or corrupt (or not mounted because they're on a network filesystem...) you can still run those commands to get the system working (and mount that networked file system with the libraries you are looking for).

True story: One sysadmin many years ago, back when an 80 megabyte hard disk was big was looking for some space. Standard compiles included debugging/symbol information and that took a few kilobytes in each binary. So, he found every executable on the system and ran strip on it. Did you know that shared libraries are 'executables' on many systems? Removing the symbol information from them prevents anything from dynamically linking to them... oops. The only things working where those in /sbin. Fortunately, there was enough there that he was able to mount the other system of the same type and copy the shared libraries back over to the messed up system...

Dynamic

You want to update a library? No problem. Just put the library in the proper spot and all is well. Yea, that's a bit simplistic, but its the idea.

$ ldd /bin/date
  linux-vdso.so.1 =>  (0x00007fff6ffff000)
  librt.so.1 => /lib64/librt.so.1 (0x00007f54ba710000)
  libc.so.6 => /lib64/libc.so.6 (0x00007f54ba384000)
  libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f54ba167000)
  /lib64/ld-linux-x86-64.so.2 (0x00007f54ba919000)

Those are all libraries that are already loaded somewhere that you don't have to have in your application. There can be some savings in disk space size because you don't need to put a full copy of libc or any other library as part of your application.

System patching becomes easier. Instead of needing to push out a patch for everything in /bin because something changed (you need to do this for /sbin), you just push out a new shared library object and update the symbolic link chain in /lib.

Drop in replacements become possible. Just provide the same API and symbols, drop in the new library and update the symbolic link chain and all should be good.

On a system that runs multiple processes (almost all of them these days... but it was a significant distinction back in old times) static libraries meant that each application running had a full copy of its libraries taking up memory resources. Shared libraries means that they can all just point to the same spot in already loaded memory.

Statically linking an application can be considered a derivative work of the libraries. This becomes an issue with GPL software. There are differing opinions on if dynamically linking a GPL licensed library creates a derivative work.

Dynamic linking allows for plugins. The application loads the plugins and dynamically calls the functions available to it.

Multiple languages can use the same calling conventions and call a dynamic library. Look at Java for an example there - dynamic linking means that Clojure, Scala, Groovy, etc... with dynamic linking they can all use the same shared libraries. Alternatively look at all the different languages that can invoke a .DLL on windows.

Related reading:

  • 2
    +1 Pretty much covers it. A line or two specifically on hot library swaps would make it perfect ... – andy256 Jun 6 '14 at 4:17
3

To me, the answer is very simple: to save resources like space. If all N applications on a system need library X, and all of them statically link this library into their executables, then there is (N - 1) (size of X) bytes you are wasting.

The reason why statically linking has survived at all is precisely because there is no system that can guarantee that all applications find installed the libraries they need, in the version that they need them, at the same time (see dependency hell).

Many solutions have been tried: keeping versioned libraries, smart package managers, even virtual machines are a way of putting a layer of indirection between your application and the system "as it is now". Each of these has led to its own hell: DLL hell, RPM hell and JAR hell.

The only bullet-proof way of deploying an executable to another machine is that it contains everything it needs to run. That is, by wasting resources.

  • I once was using a version of a library X that some sysadmin had rebuilt. He rebuilt it with some unicode flag (to satisfy another user), and it broke my app (and many others). After that the sysadmin of library X needed more version qualifiers, so he added X-utf9 and X-utf16 versions. Over 6 years library X installations on the same looked like this: X-utf8-32.1.so, X-utf8-64.1.so, X-utf16-32.1.so, X-utf16-64.1.so, X-utf8-32.2.so, X-utf8-64.2.so, X-utf16-32.2.so, X-utf16-64.2.so, X-utf8-32.3.so, X-utf8-64.3.so, X-utf16-32.3.so, X-utf16-64.3.so. No space saved. – Erik Aronesty May 17 at 13:33
1

There are advantages to each, as is the case for pretty much everything in software development.

Say I am developing a Windows application, that involves some sort of cryptographic feature. Because those functions are complicated, and rolling your own is almost always a bad idea, I instead use the libraries provided by the Windows platform.

Pretend, after awhile, a nasty bug is revealed in the Windows libraries, that causes your pets to be murdered if you visit the wrong web page.

If you dynamically linked your application to the libraries, an update can be made to the platform, and your software can be fixed of its vulnerability without you doing anything. Windows update can solve your problems.

If you statically linked your application to the libraries, you would have to recompile an updated version of your software, and distribute it to your users, and feel the guilt of all the puppies murdered while you got around to doing so.

The same principle applies for other platforms and libraries.

Additionally, dynamic linking affords the ability to have stuff like plugins. You can also update shared libraries while an application is using them, and use the new libraries once the application is restarted.

Those benefits are why we have dynamic linking.

  • As I recall, static linking is good if the libraries you are using are very large and the loading therein is a performance concern. – World Engineer Jun 6 '14 at 1:32
  • Since linking only ever happens once per application start, it would have to be a humongous library with a large number of calls into it before you would benefit from static linking. – BobDalgleish Jun 6 '14 at 2:44
  • Likewise if your perfectly secure application winds up getting "updated" because some sysadmin decides to change a shared object out from under you, you can lose your security overnight. – Erik Aronesty May 17 at 13:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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