When to use dynamic vs. static libraries

265,058

Solution 1

Static libraries increase the size of the code in your binary. They're always loaded and whatever version of the code you compiled with is the version of the code that will run.

Dynamic libraries are stored and versioned separately. It's possible for a version of the dynamic library to be loaded that wasn't the original one that shipped with your code if the update is considered binary compatible with the original version.

Additionally dynamic libraries aren't necessarily loaded -- they're usually loaded when first called -- and can be shared among components that use the same library (multiple data loads, one code load).

Dynamic libraries were considered to be the better approach most of the time, but originally they had a major flaw (google DLL hell), which has all but been eliminated by more recent Windows OSes (Windows XP in particular).

Solution 2

Others have adequately explained what a static library is, but I'd like to point out some of the caveats of using static libraries, at least on Windows:

  • Singletons: If something needs to be global/static and unique, be very careful about putting it in a static library. If multiple DLLs are linked against that static library they will each get their own copy of the singleton. However, if your application is a single EXE with no custom DLLs, this may not be a problem.

  • Unreferenced code removal: When you link against a static library, only the parts of the static library that are referenced by your DLL/EXE will get linked into your DLL/EXE.

    For example, if mylib.lib contains a.obj and b.obj and your DLL/EXE only references functions or variables from a.obj, the entirety of b.obj will get discarded by the linker. If b.obj contains global/static objects, their constructors and destructors will not get executed. If those constructors/destructors have side effects, you may be disappointed by their absence.

    Likewise, if the static library contains special entrypoints you may need to take care that they are actually included. An example of this in embedded programming (okay, not Windows) would be an interrupt handler that is marked as being at a specific address. You also need to mark the interrupt handler as an entrypoint to make sure it doesn't get discarded.

    Another consequence of this is that a static library may contain object files that are completely unusable due to unresolved references, but it won't cause a linker error until you reference a function or variable from those object files. This may happen long after the library is written.

  • Debug symbols: You may want a separate PDB for each static library, or you may want the debug symbols to be placed in the object files so that they get rolled into the PDB for the DLL/EXE. The Visual C++ documentation explains the necessary options.

  • RTTI: You may end up with multiple type_info objects for the same class if you link a single static library into multiple DLLs. If your program assumes that type_info is "singleton" data and uses &typeid() or type_info::before(), you may get undesirable and surprising results.

Solution 3

A lib is a unit of code that is bundled within your application executable.

A dll is a standalone unit of executable code. It is loaded in the process only when a call is made into that code. A dll can be used by multiple applications and loaded in multiple processes, while still having only one copy of the code on the hard drive.

Dll pros: can be used to reuse/share code between several products; load in the process memory on demand and can be unloaded when not needed; can be upgraded independently of the rest of the program.

Dll cons: performance impact of the dll loading and code rebasing; versioning problems ("dll hell")

Lib pros: no performance impact as code is always loaded in the process and is not rebased; no versioning problems.

Lib cons: executable/process "bloat" - all the code is in your executable and is loaded upon process start; no reuse/sharing - each product has its own copy of the code.

Solution 4

C++ programs are built in two phases

  1. Compilation - produces object code (.obj)
  2. Linking - produces executable code (.exe or .dll)

Static library (.lib) is just a bundle of .obj files and therefore isn't a complete program. It hasn't undergone the second (linking) phase of building a program. Dlls, on the other hand, are like exe's and therefore are complete programs.

If you build a static library, it isn't linked yet and therefore consumers of your static library will have to use the same compiler that you used (if you used g++, they will have to use g++).

If instead you built a dll (and built it correctly), you have built a complete program that all consumers can use, no matter which compiler they are using. There are several restrictions though, on exporting from a dll, if cross compiler compatibility is desired.

Solution 5

Besides the technical implications of static vs dynamic libraries (static files bundle everything in one big binary vs dynamic libraries that allow code sharing among several different executables), there are the legal implications.

For example, if you are using LGPL licensed code and you link statically against a LGPL library (and thus create one big binary), your code automatically becomes Open Sourced (free as in freedom) LGPL code. If you link against a shared objects, then you only need to LGPL the improvements / bug fixes that you make to the LGPL library itself.

This becomes a far more important issue if you are deciding how to compile you mobile applications for example (in Android you have a choice of static vs dynamic, in iOS you do not - it is always static).

Share:
265,058
Morten Christiansen
Author by

Morten Christiansen

I'm a software developer at UVdata in Denmark. I work on all sorts of interesting .NET technologies at work and in my spare time with a focus on the web. I have a passion for the craft/art of software development and love to explore the intricacies of good software design and code practices.

Updated on December 22, 2020

Comments

  • Morten Christiansen
    Morten Christiansen over 3 years

    When creating a class library in C++, you can choose between dynamic (.dll, .so) and static (.lib, .a) libraries. What is the difference between them and when is it appropriate to use which?

  • bk1e
    bk1e over 15 years
    Rebasing can also be done at build time using rebase.exe or by passing the /BASE option to link.exe. Whether this is effective depends on whether there are any unexpected address space conflicts at runtime.
  • Venedictos
    Venedictos about 15 years
    On Windows/Mac (no package manager) there is really no good reason to use dynamic libraries over static. Since Windows DLLs are not relocatable, code sharing often does not work (and usually each app ships and uses its own versions of the library anyways). The only real benefit is that it is easier to update the library.
  • Orion Adrian
    Orion Adrian about 15 years
    What, specifically, do you mean by relocatable?
  • Ravikumar Thirumani
    Ravikumar Thirumani over 14 years
    on the mac, I use a lot of dynamic libraries. for example, mac os x has sqlite3 embed. i created a program that has a sqlite3 database feature for performance storing. however, because it is rarely used dynamic linking saves on compile time, makes testing easier/faster however, if I were to build a release version, I think I would always use static library just in case of compatibility issues
  • Orion Adrian
    Orion Adrian about 14 years
    As for the point about singletons, don't forget that a DLL might be loaded multiple times (same version or mulitple versions) and there's still no singleton guarantee.
  • Tim
    Tim about 14 years
    You might also use a DLL when multiple other applications use the same functionality - this can reduce footprint.
  • Tim
    Tim about 14 years
    Also, extending your initial concept, "plug-in" architecture where you want to allow added/unknown functionality later without having to rebuild or re-release can only be done with dynamic libraries.
  • dma_k
    dma_k over 13 years
    @Zifre: relocatable = can be loaded at different virtual address. DLL certainly supports this.
  • Venedictos
    Venedictos over 13 years
    @dma_k: Windows DLLs can be loaded at different addresses, but only because the linker copies all the code and changes the address numbers. With shared objects, all the address references are relative, so multiple processes can share the same memory for the shared object. In other words, on Windows, A 1 MB DLL used by 3 programs = 3 MB. On Linux, A MB SO used by 3 programs = 1 MB.
  • Orion Adrian
    Orion Adrian over 13 years
    Additional point about unreferenced code removal: Calls made to DLLs also require an actual call to force the loading of the referenced DLL. Adding it as a reference, but then not including any call that references it will still get you the same result as having a static libary that doesn't call anything. The only difference is what actually ships. In both cases the static constructors and destructors don't fire.
  • clemahieu
    clemahieu almost 11 years
    Both Windows and Linux has the concept of load-timte relocation of shared libraries eli.thegreenplace.net/2011/08/25/… The biggest thing that allowed Position Independent Code wasn't something special to Linux, rather RIP-relative addressing added with the x64 instruction set; both Windows and Linux can make use of RIP relative addressing do reduce the number of fixups when relocating libraries.
  • Miles Rout
    Miles Rout over 10 years
    @bk1e That shouldn't happen. the .a will always contain all the symbols it was built with. When it's statically linked into your application, yes only those symbols that are used will be linked in.
  • Paceman
    Paceman over 10 years
    Aren't you meant to use some pre-compiler directives in some way to avoid code duplication?
  • gast128
    gast128 almost 9 years
    Afaiac precompiling only works on a per module (exe / dll /lib) base. Precompiling is primarly meant to speed up compilation though it also prevents multiple inclusions within a compilation unit. However include guards are the better way to achieve this effect.
  • Colin
    Colin over 8 years
    Static libraries have worse interoperability and are harder to use in, e.g., .NET environments.
  • Jämes
    Jämes about 7 years
    This is worth mentioning that sometimes, due to license constraints, you need to dynamically link your applications with libraries if you wish to keep your code base closed, such as Qt with LGPL.
  • Dan
    Dan about 6 years
    This is news to me. What restrictions are there with cross compilers when using DLLs? Having the programmer build without needing the same toolchain seems like a huge plus for DLLs
  • truthadjustr
    truthadjustr about 4 years
    This answer is informative. Adding minor caveat: consumers of your static library will have to use the same compiler that you used if the static library uses C++ library, such as #include <iostream>.
  • chris
    chris almost 4 years
    one cannot consume a c++ dll unless the same compiler is used (because there is not standard c++ abi, symbols are mangled in different ways). Both the dll and the client module must use the same compiler and same build settings
  • ed9w2in6
    ed9w2in6 over 3 years
    Would there be any performance difference between StaticLib & SharedLib once the code is fully loaded in the process?
  • als0052
    als0052 about 2 years
    I don't yet understand most of your post but +1 for specific things for us Windows scrubs.
  • Louis Go
    Louis Go about 2 years
    Please laborate on how you acheive cross compiler compatibility by building dynamic library. I recalled you'd get hiccups even across gcc and clang. Though they try to follow the same ABI standard. If a real cross compiler shared library is created, I'd say only the one with C signatures.