Section C.2. Understanding the Linker

Figure C.1 shows how the linker accepts binary files, which were generated by the compiler, and creates executable binaries as its output. The linker executable, on *nix machines is simply called ld, and it is run by g++ after all source files are compiled successfully.

Figure C.1. The linkers inputs and outputs


All of these steps are performed when you run make, which prints out every command before it executes. By reading the output of make, you can see what arguments are being passed to the compiler and linker. When an error occurs, it immediately follows the command line that produced the error.

Example C.3 shows the command line options passed to g++, and attempts to show how g++ runs the linker, known as ld, and also passes some arguments to it.

Example C.3. linker-invocation.txt

g++ -Wl,-rpath,/usr/local/qt-x11-free-3.2.3/lib <-- 1
 -o hw7 <-- 2
 .obj/address.o .obj/ca_address.o .obj/constraintgroup.o
 .obj/customer.o .obj/dataobject.o .obj/dataobjectfactory.o
 .obj/hw07-demo.o .obj/us_address.o .obj/moc_address.o <-- 3
 .obj/moc_ca_address.o .obj/moc_customer.o .obj/moc_dataobject.o
 .obj/moc_us_address.o
 -L/usr/local/qt-x11-free-3.2.3/lib -L/usr/X11R6/lib
 -L/usr/local/utils/lib <-- 4
 -lutils -lqt -lXext -lX11 -lm <-- 5

(1)Tells g++ to run the linker, and pass these options to ld.

(2)Specify the output to be called hw7.

(3)Link these object files into the executable.

(4)Add another location for the linker to search for libraries.

(5)Link this app with five more libraries: qt utils, ext, X11, and m

Linking entails the following:

  • For each library name passed with the -l switch, find the corresponding library file, searching the library path, as well as all -L switched arguments (which were generated by qmake from the LIB qmake variable).

    • For static libraries, it contains the code to be linked into the executable.
    • For dynamic libraries, it is a catalog listing (often in readable ascii format) that describes where the actual shared objects are for each label definition. The linker will check to make sure the shared object is where it should be, and report an error if not.
  • For each function that is called from any place in the code we are linking, find the object where that code is located and do a simple, fast check to determine that there is, indeed, a completely defined function with the proper name/signature at that location. Report an error if it can be found or isn the correct type/name/size.
  • For each reference to a variable name, find the object-address where that variable is located and do a simple, fast check to make sure the address is a valid one for an object of that type.

This is the general idea. The linker resolves references to names by finding their real addresses in files and checking the addresses to determine whether they e valid for the type id. Its like a directory look-up service for C++ compilers.

C.2.1. Common Linker Error Messages

C++ programmers sometimes spend lots of time trying to understand and repair compiler and linker errors. If you can understand the message, you e stuck. With a compiler error, the problem is easier to diagnose because it is related to the compilation of one source code module and the header files it includes. The compiler generally tells you the exact location of any error that it detects. With a linker error, the problem is related to how your source code modules link together. When the linker stage is reached, all the individual modules have compiled without errors. Linker errors can be caused by bugs in C++ code, but they can also be a result of mistakes in the project file.

C.2.1.1. Unable to Find libxxx.so.x

For Win32 Users

At build-time, your IDE needs to be able to find the .DLL. To configure it, drill into your menu structure until you find project -> properties -> c/c++ build -> libraries. Here you can add a third-party library, and youll be asked in a dialog for the location of headers and DLL files.

At runtime, your PATH system environment variable must contain the directory where the required DLLs are located.


Installing a library means making it available for more than a single user on a system. It is also possible to reuse a library without installing it. All libraries that you reuse must either be installed or placed in a directory listed in your LD_LIBRARY_PATH.

When you are reusing a library for the first time, you will probably see this error message. It means that the linker cannot find the library. When the gnu linker looks for a shared object, it checks at least two places:

  1. The directories specified in LD_LIBRARY_PATH

  2. Installed libraries referenced from a cache file called /etc/ld.so.cache

The Cache File ld so cache

The cache file provides fast lookup of shared objects found in the directories specified in /etc/ld.so.conf. Some directories you might find there are

/lib

/usr/lib

/usr/X11R6/lib

/usr/i486-linuxlibc1/lib

/usr/local/lib/usr/lib/mozilla

If you use a Linux package installer to install a library, it will probably make the proper changes to ld.so.conf and rebuild your cache file. However, if you manually compile and install libraries, it may be necessary for you to edit this file. Afterwards, you can rebuild the cache file with the command ldconfig.


C.2.1.2. Undefined Reference to [identifier]

This is the most common and probably the most annoying linker error of all. It means that the linker cannot find the definition of some named entity in your code. Here is some output from make.

.obj/ca_address.o(.gnu.linkonce.t._ZN10DataObject16getConstraint-
MgrEv+0x4):
In function DataObject::getConstraintMgr():
/usr/local/qt-x11-free-3.2.3/include/qshared.h:50:
undefined reference to DataObject::sm_Cm
collect2: ld returned 1 exit status
make: *** [hw7] Error 1


The compiler found the declaration, but the linker can find the corresponding definition. In some part of your code, you are referencing a symbol, but there is no definition found. The useful bits of information are

  • The symbol it can find is DataObject::sm_Cm.
  • The function that is trying to use it is DataObject::getConstraintMgr.

The first step is to determine whether we, as humans, can find the missing definition. If we can , how can the linker? If we find it in a .cpp file, we must make sure that

  • Both the .cpp and the .h file are mentioned in the project
  • The file is included in a library with which we are linking

Because we are using good naming conventions (see Section 3.4), we can immediately tell that sm_Cm is a static data member of class DataObject. The compiler found the declaration, but the linker can find the definition.

Because it is static (Section 2.10), the definition for sm_Cm belongs in dataobject.cpp. The compiler expects to find a definition statement of the form:

ConstraintMgr DataObject::sm_Cm;


If its there and the linker still can find it, the most likely causes for this error are

  • The .cpp file that contains the definition is not listed in qmakes SOURCES in the .project file.
  • The code is located in another library but the linker can find the library. This is solved by adding a missing LIBS argument in the project file.

    • -lmylib adds a library to be linked.
    • -Lmylibdir adds a directory to the linkers lib search path list.
C.2.1.3. Undefined Reference to vtable for ClassName

This is one of the most confusing errors. It generally means that a virtual function definition is missing. Literally, the vtable for that class (which has addresses of each the virtual functions) is unable to be fully constructed.

This error can arise from missing function definitions in your code, but it can also be caused by a missing HEADERS or SOURCES enTRy in your make/project file. The resolution is to double-check that all files are listed properly in the project file before you delve too deeply into your C++ code.

All inline Classes

For polymorphic classes,[3] there should be at least one non-inline definition (function or static member) in a source (.cpp) file for that header file. Without this, many linkers will not be able to find any of its virtual method definitions.

All-inline classes are legal in C++, but they do not work in their intended way when mixed with polymorphism.


[3] classes with at least one virtual method



Part I: Introduction to C++ and Qt 4

C++ Introduction

Classes

Introduction to Qt

Lists

Functions

Inheritance and Polymorphism

Part II: Higher-Level Programming

Libraries

Introduction to Design Patterns

QObject

Generics and Containers

Qt GUI Widgets

Concurrency

Validation and Regular Expressions

Parsing XML

Meta Objects, Properties, and Reflective Programming

More Design Patterns

Models and Views

Qt SQL Classes

Part III: C++ Language Reference

Types and Expressions

Scope and Storage Class

Statements and Control Structures

Memory Access

Chapter Summary

Inheritance in Detail

Miscellaneous Topics

Part IV: Programming Assignments

MP3 Jukebox Assignments

Part V: Appendices

MP3 Jukebox Assignments

Bibliography

MP3 Jukebox Assignments



An Introduction to Design Patterns in C++ with Qt 4
An Introduction to Design Patterns in C++ with Qt 4
ISBN: 0131879057
EAN: 2147483647
Year: 2004
Pages: 268

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net