When loading programs into memory, what is the difference between load-time dynamic linking and run-time dynamic linking?
In load-time dynamic linking executable is linked to the DLL Library while in Runtime dynamic linking no executable was linked o any DLL.
Runtime dynamic linking is preferable when the startup performance of the application is important
load-time linking is when symbols in the library, referenced by the executable (or another library) are handled when the executable/library is loaded into memory, by the operating system.
Run-time linking is when you use an API provided by the OS or through a library to load a DLL or DSO when you need it, and perform the symbol resolution then.
I know more about Linux DSOs than Windows DLL's but the principle should be the same. .NET libraries may differ.
In linux, plugin architectures are done this way. Your program will use runtime linking to load up a library and call some functions. Then maybe unload it. It also allows multiple libraries with the same symbols exported to be loaded without clashing. I think DLLs will work in much the same manner.
Executables have "blank spaces" in their symbol tables that need filling by some library. These blank-spaces are usually filled in at load-time, or compile time. You can negate the need for "blank spaces" in the symbol table by using runtime linking.
Another scenario where runtime linking is useful is for debugging libraries, or selecting from multiple, ABI/API compatible libraries at runtime. I often have a library, say "foo" and one called "foo_unstable" and have a test app that switches between the 2 and does some testing.
Under linux, to see what libraries an executable links to at load-time you run the ldd
command and get output such as (on /bin/ls):
linux-vdso.so.1 => (0x00007fff139ff000)
librt.so.1 => /lib64/librt.so.1 (0x0000003c4f200000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003c4fa00000)
libcap.so.2 => /lib64/libcap.so.2 (0x0000003c53a00000)
libacl.so.1 => /lib64/libacl.so.1 (0x0000003c58e0000
The operating system will attempt to load the libraries (the .so files) at load-time. It may already have the library in memory.
Aiden Bell covered the fundamentals, but I'll add:
Load time dynamic linking is usually accomplished by statically linking your application to a .lib
or .a
file that contains the code for automatically establishing runtime links to symbols to be found in .dll
or .so
files at program startup. This is usually for fixed functionality (i.e. the C runtime library, etc.) and allows your program to reap the benefits of bug fixes in the libraries while keeping executable size small (by factoring common code into a single library).
Runtime linking is used for more dynamic functionality such as plugin loading. As Aiden said, you use LoadLibrary()
or the equivalent to actively attach modules to your program at runtime, perhaps by interrogating a directory containing plugin DLLs, loading each one in turn and talking to it with a homegrown plugin API. By doing so, your program can load modules that did not even exist when your app was compiled/linked, and can thus grow organically after deployment.
Fundamentally both methods end up invoking the LoadLibrary()
API, but using a fixed set of symbols and libraries in the former case and a more dynamic set in the latter.
It has been a long time since the question was asked. And Aiden and Drew's answers covered most of the essence. I just want to add a few things from a programmer's perspective.
If you use Load-Time Dynamic Linking, we have to link to the LIB file. And then in the code, we can call the method as explicitly as usual. (See Using Load-Time Dynamic Linking for the code sample)
If you use Run-Time Dynamic Linking, you have to manage the DLL loading/freeing, and function lookup yourself. (See Using Run-Time Dynamic Linking for the code sample)
For a choice between the 2 options, check Determining Which Linking Method to Use.
So, I think the Load-Time Dynamic Linking is just another way to save programmers' effort. But it comes at the price of some extensibility. You can only use the DLL corresponding to the LIB files you use as the import library.
Fundamentally, both linking approaches use the LoadLibrary() API on Windows platform.
Load Time premature optimize away the GetProcAddress()
by creating a fixed offset from the start of the DLL. Older executables cannot work with newer DLLs violating the Open Principle of SOLID; newer executables cannot work with older DLLs because the function offset may be different so it violates the Close Principle of SOLID. You get DLL-HELL when you violate SOLID.
Run Time cannot premature optimize away the GetProcAddress()
calls. Older executables could work with newer DLLs, but cannot use the new functions adhering to the Close Principle of SOLID; newer executables could work with older DLLs, but cannot use the new functions adhering to the Close Principle of SOLID. The comparison of using older executables with older DLLs, and using newer executables with newer DLLs is the adherence of the Open Principle of SOLID.
Hot Code Reloading
is Object Oriented Programming
. You fail Liskov Substitution Principle
where the newer DLL cannot be used with an older executable, or where the older DLL cannot be used with a newer executable. Newer versions are inheritance
of older versions regardless if they are executables or DLLs.