Applications, Static Libraries and DLLsFiled Under: Weekly Tuesday Dose of goodness
Hi all,
This week I’ll talk about the 3 main types of projects that are created with C/C++. We’ve perhaps heard of the term library, framework and engine. However, for this post, we’re talking about a low level set of articles which defined a certain development strategy.
Not everything is built directly as an application. Some applications have dependencies, some have extensions during run time, while others have a mix of both.
Whatever it is - there’s a need to understand what their differences are so that we know when to use what. Read on the find out more.
Introduction
So why are there applications (.exe), static libraries (.lib or .a) and Dynamic-linked library (.dll or .so)? The reason is simple - some information is known before execution, some information can only be available during execution.
In Windows, a DLL is also an application indirectly. Which is why sometimes you see a DLL runner known as rundll.exe. This file allows you to run a DLL alike an application.
In Linux or Solaris, a DLL equivalent is known as a Shared Object thus having the extension of (.so).
Static Libraries on the other hand, are programs that are pre-defined and pre-declared for an application to use. They cannot run on their own and usually require an application to fill up the rest of the blanks.
Applications (.exe)
The first thing we were taught in schools when building applications in C is to include this header file known as stdio.h.
Most people will understand that this is a requirement, but will not fully understand why is it a requirement.
Reason is very simple. All applications need a starting point. This starting pointer is usually offered by runtime libraries such as the CRT. Thus if you attempt to build any applications without defining a main() for example, the linker will complain that there’s something unresolved.
This is how the CRT works. It’ll call your main() to kick start the whole process.
Static Libraries
These guys on the other hand, are functionalities that are built in. For one, CRT itself is a static library as well even though it uses some dynamic libraries during runtime (for Windows).
A static library usually comes in a package as follows:
1) A single .lib or .a file
2) A bunch of header files
Static libraries also have several special characteristics. I’ll list 2 below:
1) They do not need to link.
2) They allow declarations without definitions.
What are declarations and what are definitions? Well… I guess that’s up to you to find out right? After all, if you do not know this 2 terms, you’ll probably have a hard time reading this article as well.
DLLs(Dynamically-Linked Libraries)/Shared Objects
Although it sounds as though as it’s a static library loaded during run time, the truth is far from it. A DLL is essentially an application by itself. It may share a heap based on the CRT used for compilation, ie, (Multi-threaded Debug DLL, Multi-threaded DLL), but there’re a few things that they’ll definitely have on their own.
For example: private heap.
Thus the notion of a singleton that exists one and only in an application is only as true as the application itself. If the application extends by loading other dynamic modules during run time, that module does not have inherent access to the application’s private heap.
That means, don’t expect to access the same singleton instance when you call getInstance().
This however, is usually ignored since we’re encouraged not to put any data attributes into singletons due to its non-deterministic order of destruction.
Dynamic libraries however, have the distinct advantage of quick builds and deployment. Since the DLL needs only what it needs during linking, yes DLL needs to be linked, the overall build time is usually much shorter than the static library or the application. Subjected to project size of course.
Since the DLL is only linked during runtime, there’s no need to link into the main application everytime a change is made.
However so, DLLs have its disadvantages as well. In particular to the versioning of the DLL. If one or more DLL uses the same set of base classes and that the application’s base class binaries are newer than the ones linked onto the DLLs, then there’s a chance of a code misalignment.
When that happens, even if functions like GetProcAddress() works, any calls to the base classes will have an undefined behavior. Reason is because, the memory address of the code memory is mapped. Every function or method has an absolute code address. This mapping is changing whenever a method/function is added or removed.
This causes the expected function/method address to go off alignment and illegal memory access thus causes the application to crash unexpected without any clues.
The second level of impact is when the codes of the base classes were changed. This change may reflect a change of logic and thus produce erroneous results. The results can range between just a weird value to a wild or dangling pointer, in which will lead to a crash as well.
All these problems are associated with the symptom known as DLL HELL.
And such problems are extremely hard to fix unless there’s a strong technical lead to highlight the possibilities. On top of that, if the DLLs are from third party libraries, good luck!
Misuse
I don’t know if it’s just me or what but I usually encounter a few companies who tend to claim that they link to the DLL during the main build process.
As far as my limited knowledge can tell me, it doesn’t make any sense to link to any DLLs during the main build process.
If that’s the case, the DLL should just be a static LIB instead.
It’ll be a shame however, if these people continue to believe that they’re linking to a DLL during the build and then continue to load the DLL during runtime.
That’ll end up having two separate sets of binaries loaded and they’ll not even know exactly which piece of code is used! In short, isn’t this a recipe for disaster?
Conclusion
Finally, I’ll just like to round up the use of the 3 different types of build outputs.
An application is what it is, a standalone and executable application. It requires all compilation to work (except for template codes that are not used) and requires all symbols to be linked before it can be produced as an executable.
A static library is a collection of preprocessed object files which contains usually, logic and workflow. It may not necessary have all the symbols defined even when there’s declaration for it. A static library requires all codes involved to be compilable but doesn’t require any linking.
Finally, a dynamic linked library is also an application by itself but allows itself to be loaded as part of an application as a module. It requires all codes to be compilable as well as all symbols to be linked as well.
A DLL is extremely suited to be implemented with the Bridge Pattern in OO, where GetProcAddress retrieves a function that creates an instance of itself and returns a pointer of its interface to the caller.
The caller will then access all available functionalities based on the promise of the interface.
This allows multiple DLLs to implement the same interface without having the application to know of their existence at all. However, I won’t go into details on how to implement this just yet.
Anyway, I have a plane to catch! Have a nice week ahead and yeah - to all Singaporeans (as well as myself), Happy National Day!
Signing off,
Jeremy
- Permalink
- Admin
- 10 Aug 2010 8:13 AM
- Comments (0)