Dynamic Libraries in depth and it's differences with Static Libraries

Dynamic Libraries in depth and it's differences with Static Libraries

This article is focused on:

  • Why using libraries in general
  • How do they work
  • How to create them (Linux only)
  • How to use them (Linux only)
  • What are the differences between static and dynamic libraries
  • What are the advantages and drawbacks of each of them

let's dive in!

To start with the libraries, we need to refresh some concepts about the compilation process. Briefly: every time we compile a file, we gave the compilator (GCC) a file with code, that is understandable for humans at the end of the process, this code will be translated into machine code and we will get an executable file as result. Here are the phases and process explained in further detail:


What are libraries then?

Every library consists of two parts: a header file and the actual code file. The header file, normally denoted by a .h suffix, contains information about the library that programs using it need to know. In general, the header file contains constants and types, along with prototypes for functions available in the library. . The compilation process is important to understand this concept, since the libraries will be linked in the last phase. That means, any librarie you use will be linked to your code during the las phase of the compilation process.

So, if it so... as we know, at the end of the compilation process the code will not look like C code or any other language, it will be something more like assembly code, that's why we need to compilate and play a little bit to create a library, so that the code can be added to any file we want to compilate.

Why using libraries in general

As a project grows, you will probably want to reuse some code or functions in other programs you write. At this point the libraries become super useful.

Normally the libraries are indexed, so it is easy to find symbols (functions, variables and so on) in them. For this reason, linking a program whose object files are ordered in libraries is faster than linking a program whose object files are separate on the disk. Also, when using a library, we have fewer files to look for and open, which even further speeds up linking.

If you have ever written a C program, you may have called the standard library :)

#include <stdlib.h>        

by doing this, you are telling the linker (at the end of the compilation process) to include all the functions that are into the header of the library "stdlib.h". This is why they are so useful!, knowing this, you can create your own functions and get them together into your own library. How cool is that?

There are two kinds of libraries:

Static vs Dynamic libraries: differences, advantages a drawbacks of each.

Static libraries are just collections of object files that are linked into the program during the linking phase of compilation, and are not relevant during runtime. For more details, visit this article about static libraries. (What are they, how to create them and how to use them)

Dynamic libraries (aka shared libraries) are linked into the program in two stages. First, during compile time, the linker verifies that all the symbols (again, functions, variables and the like) required by the program, are either linked into the program, or in one of its shared libraries. However, the object files from the dynamic library are not inserted into the executable file. Instead, when the program is started, a program in the system (called a dynamic loader) checks out which shared libraries were linked with the program, loads them to memory, and attaches them to the copy of the program in memory.

The complex phase of dynamic loading makes launching the program slightly slower, but this is a very insignificant drawback, that is out-weighted by a great advantage - if a second program linked with the same shared library is executed, it can use the same copy of the shared library, thus saving a lot of memory. For example, the standard "C" library is normally a shared library, and is used by all C programs. Yet, only one copy of the library is stored in memory at any given time. This means we can use far less memory to run our programs, and the executable files are much smaller, thus saving a lot of disk space as well.

However, there is one drawback to this arrangement. If we re-compile the dynamic library and try to run a second copy of our program with the new library, we'll soon get stuck - the dynamic loader will find that a copy of the library is already stored in memory, and thus will attach it to our program, and not load the new (modified) version from disk

In this image we can see the main difference between the libraries and why the dynamic libraries are known as "shared".

How to create a dynamic library:

Step 1: compile to get object files

Suppose you want to create a library called "cisfun". The first step will be to compilate the functions you want to index to the library. As I mentioned, the linker will take the code inside the libraries and index to the program you want compile.

gcc -Wall -fPIC -c *.c        


To achieve this, two flags are used:

  1. The -Wall enables all compiler's warning messages. This option should always be used, in order to generate better code.
  2. The -fPIC - or Compile for "Position Independent Code" - When the object files are generated, we have no idea where in memory they will be inserted in a program that will use them. Many different programs may use the same library, and each load it into a different memory in address. Thus, we need that all jump calls ("goto", in assembly speak) and subroutine calls will use relative addresses, and not absolute addresses. Thus, we need to use a compiler flag that will cause this type of code to be generated.
  3. The -c option says not to run the linker. Then the output consists of object files output by the assembler.

And the *.c wildcard, which tells the compiler to convert all the .c files in the current directory

Step 2: Create the library :D

After the last step will see that all the .c files we had will be converted to object files with the .o extension. Now, we are ready for the next command.

gcc -shared -o libdynamic.so *.o        


As a convention, all the library names should start with the "lib" prefix, so our library will be called libdynamic.so, the .so suffix stands for Shared object.

How to use it


Step 1. Install your shared library

On GNU glibc-based systems, including all Linux systems, starting up an ELF binary executable automatically causes the program loader to be loaded and run. On Linux systems, this loader is named /lib/ld-linux.so.X (where X is a version number). This loader, in turn, finds and loads all other shared libraries used by the program.

You'll need to install it somewhere, and then give your program enough information so the program can find the library... and there are several ways to do that. You can use gcc's -L flag in simple cases. You can also use environment variables to control things. In particular, you can set LD_LIBRARY_PATH, which is a colon-separated list of directories in which to search for shared libraries before the usual places.

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH         


This command will tell the loader to look for the new shared library into the current directory :)

There is another way to install the library using the ldconfig command:

The ldconfig utility scans the directories where the dynamic libraries are commonly found (/lib and /usr/lib) as well as the directories specified in /etc/ld.so.conf and creates both symbolic links to these libraries and a cache (stored on /etc/ld.so.cache) containing their locations so that ld-linux.so can quickly find them whenever necessary. This is done when you run ldconfig without any arguments or with the -n option to tell the loader to look for the current directory

 ldconfig -n .        



Step 2. Compile the shared library into your program

To use a dynamic library you need to compile the library with your main program, for this example the library is called cisfun.so and the main program just main :)

gcc -Wall -pedantic -Werror -Wextra -L. main.c -ldynamic -o main        


To compilate we are using two extra flags, the -l tells the compiler to look for a file called libcisfun.so and the -L tells the linker that the library is located in the current directory.

now you are ready to execute the main program using

./main         


Have fun coding :)


To view or add a comment, sign in

More articles by Santiago Goyret

Others also viewed

Explore content categories