Previous section   Next section

Imperfect C++ Practical Solutions for Real-Life Programming
By Matthew Wilson
Table of Contents
Chapter 9.  Dynamic Libraries


9.2. Indentity: Link Units and Link Space

9.2.1 Link Units

Static libraries are, by definition, incomplete. If they weren't, they'd be executables. This means that there exist some unresolved symbol references in the static library, or that it does not contain an executable entry point conformant to the operating system or virtual machine for which it resides, or both. It's the same for objects (with external linkage): they need only be declared.

By contrast, a dynamic library, like an executable, is complete. There exist no unresolved symbols, save for those that refer to system libraries and/or other dynamic libraries. And any referenced objects must be defined within the link unit.

In the minutiae this distinction is a bit wavy—for example, a dynamic library may not always contain an entry point—but conceptually it is quite clear.

9.2.2 Link Space

The significance of the link unit is more salient when we consider the link space. For the classic standalone executable model, the link space is the combination of all the object files and static libraries. Within the link space there can be only one instance of each symbol and each object (variable with external linkage). Whether we are talking about just plain old C objects, such as arrays, or C++ first-class objects, any static objects in the link unit are resolved when the link unit is built. The same applies to all link units, including dynamic libraries. Within each dynamic library exists one copy of all the functions and objects from which it is comprised.

(Note that I'm glossing over the fine details regarding dependencies of link units on other link units. For example, an executable may depend on a dynamic library, and therefore will not contain within itself the actual functions on which it will rely. However, it will contain information enabling the operating system loader to fix up those dependencies, so it can be thought to be notionally complete. Further, dynamic libraries can export objects as well as functions, and so a link unit may share an object with another by this mechanism. Again, this is a detail that you should be aware of, but that does not detract from the main point about link spaces.)

This notion of multiple copies is crucial to the successful use of dynamic linkage, and it is especially significant for C++ and the use of static objects. Whenever code within a given link-space references an object by name, it references the one within the same link space.

9.2.3 Multiple Identities

Let's consider a simple case to illustrate what this means. A classic example for the use of statics is the instance counter, whereby each constructor of the class increases the instance counter. In that way, you can monitor the total number of instances of your class that were used in the application. But if you have defined the static member within each link unit, you will only get a reading for the number of instances created within the link unit from which you are calling. If you're sharing such classes between link units, this kind of thing does not represent a problem, but if you're not, you need to be aware of it.

Another area in which you can't escape it is where you have inline code (whether class methods or free functions) that contains function-local static objects. In this you most certainly will end up with different instances in different link units, irrespective of any code sharing. We saw an example of this in the last chapter, when synthesizing compiler-independent vtables. In that case, the separate instances per link unit were actually required, but most uses of function-local statics do not require it and some may assume its absence. We'll see more regarding the care required for function-local statics in the remaining chapters of this part.


      Previous section   Next section