Creating an Executable from Your Source Files - Practices
This article will give you a good understanding of the basic concepts and practices of the C++ language, so that you will have the foundation to eventually learn these ideas in detail as you continue working with the language. It is excerpted from Ivor Horton's Beginning ANSI C++ The Complete Language (Apress, 2004; ISBN 1590592271).
Creating a program module that you can execute from your C++ source code is essentially a two-step process. In the first step, your compiler converts each .cpp file to an object file that contains the machine code equivalent of the source file contents. In the second step, the linker combines the object files produced by the compiler into a file containing the complete executable program.
Figure 1-5 shows three source files being compiled to produce three corresponding object files. The filename extension thatís used to identify object files varies between different machine environments, so it isnít shown here. The source files that make up your program may be compiled independently in separate compiler runs, or most compilers will allow you to compile them in a single run. Either way, the compiler treats each source file as a separate entity and produces one object file for each .cpp file. The link step then combines the object files for a program, along with any library functions that are necessary, into a single executable file.
Figure 1-5.The compile and link process
In practice, compilation is an iterative process, as youíre almost certain to have made typographical and other errors in the source code. Once youíve eliminated these from each source file, you can progress to the link step, where you may find that yet more errors surface! Even when the link step produces an executable module, your program may still contain logical errors; that is, it doesnít produce the results you expect. To fix these, you must go back and modify the source code and start trying to get it to compile once more. You continue this process until your program works as you think it should. As soon as you declare to the world at large than your program works, someone will discover a number of obvious errors that you should have found. It hasnít been proven beyond doubt so far as I know, but itís widely believed that if a program is sufficiently large, it will always contain errors. Itís best not to dwell on this thought when flying.
Letís take a closer look at what happens during the two basic steps, compiling and linking, because there are some interesting things going on under the covers.
The compilation process for a source file has two main stages, as illustrated in Figure 1-6, but the transition between them is automatic. The first stage is the preprocessing phase, which is carried out before the compilation phase proper. The preprocessing phase modifies the contents of the source file according to the preprocessing directives that you have placed in the file. The #include directive, which adds the contents of a header file to a .cpp file, is an example of a preprocessing directive, but there are many others (as youíll see in Chapter 10).
Figure 1-6.Details of the compilation process
This facility for modifying the source file before it is compiled provides you with a lot of flexibility in accommodating the constraints of different computers and operating system environments. The code you need in one environment may be different from that required for another because of variations in the available hardware or the operating system. In many situations, you can put the code for several environments in the same file and arrange for the code to be tailored to the current environment during the preprocessor phase.
Although preprocessing is shown in Figure 1-6 as a distinct operation, you donít execute it independent of the compiler. Invoking the compiler will perform preprocessing automatically, before compiling your code.
Although the output from the compiler for a given source file is machine code, itís quite a long way from being executable. For one thing, there will be no connection established between one object file and another. The object file corresponding to a particular source file will contain references to functions or other named items that are defined in other source files, and these will still be unresolved. Similarly, links to library functions will not yet be established; indeed, the code for these functions will not yet be part of the file. Dealing with all these things is the job of the linker (sometimes called the linkage editor).
As Figure 1-7 illustrates, the linker combines the machine code from all of the object files and resolves any cross-references between them. It also integrates the code for any library functions that the object modules use. This is actually a simplified representation of what the linker does, as weíre assuming that all the links between modules are established statically within the executable module. Itís also possible for some links to be dynamic; that is, theyíre established only when the program executes.
Figure 1-7.Details of the linking process
As I said, the linker establishes links to functions staticallyóthat is, before the program executes. This is done for all the functions contained in the source files that make up the program. Functions linked to dynamicallyóthat is, during program executionó are compiled and linked separately to create a different kind of executable module called a dynamic link library (DLL).A link to a function in a DLL is established when the executable module for your program calls the function, and not before.
DLLs present several important advantages. A primary one is that the functions in the DLL can be shared between several programs that are executing concurrently. This saves using up memory with duplicates of the same function when more than one program is executing that requires the services provided by the functions in the DLL. Another advantage is that the DLL wonít be loaded into memory until one of the functions it contains is called. This implies that if you donít use a function from a given DLL, it wonít occupy space in memory. DLLs are a system capability that ties in closely with your operating system, so I donít discuss them further in this book.
This article is excerpted from Beginning ANSI C++ The Complete Language by Ivor Horton (Apress, 2004; ISBN 1590592271). Check it out at your favorite bookstore today. Buy this book now.