6.3. Diagnosing link-time errors

The C and C++ compiler drivers (see 1.7.1, “Default compiler drivers” on page 30) handle object file linking by invoking the system link editor ld with the appropriate options and flags. There is no need to use ld directly to link edit your C and C++ object files. This section describes some of the more common link-time errors that you may encounter during development.

6.3.1. Unresolved symbols

When linking your application with many libraries, particularly those supplied by a third party product, such as a database, it is not unusual during the development cycle to see a linker error warning about unresolved symbols.

The system link editor accepts input such as object files, shared object files, archive object files, libraries, and import and export files, resolves external symbol references, and creates a single executable object file that can be run. When an external symbol cannot be resolved, the link would fail and an executable is not generated.

Unresolved symbol errors can occur in many situations, the most common being missing input files. For example, if you call a library function that is not in the default C run-time library libc.a, you need to specify the archive library file in which the symbol is found:

$ cat test.c
#include <stdio.h>
#include <math.h>
void main()
{
    printf("%f
", pow(2.0,3.0));
}
$ cc test.c
ld: 0711-317 ERROR: Undefined symbol: .pow
ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.
$ cc test.c -lm

This is especially true when using functions provided by third-party libraries. Aside from searching the product documentation, finding the library file in which an unresolved symbol is defined can be quite a daunting task. You can include all supplied libraries in the link command and let the link editor find out where the symbol is, or you may use the nm command to try find it yourself.

The linker supports options that can be used to generate linker log files. These log files can then be analyzed to determine the library or object file that references the unresolved symbol. This can help in tracking interdependent or redundant libraries being used in error.

The -bnoquiet option writes each binder sub command and its results to standard output. It gives a better of picture of the unresolved symbol references if any exists and also the list of symbols imported from the specified library modules.

The -bmap:filename option is used to generate an address map. Unresolved symbols are listed at the top of the file, followed by imported symbols.

The -bloadmap:filename option is used to generate the linker log file. It includes information on all of the arguments passed to the linker along with the shared objects being read and the number of symbols being imported. If an unresolved symbol is found, the log file produced by the -bloadmap option lists the object file or shared object that references the symbol. In the case of using libraries supplied by a third-party product, you can then search the other libraries supplied by the product in an effort to determine which one defines the unresolved symbol. This is particularly useful when dealing with database products that supply many tens of libraries for use in application development.

If errors show up during linking or loading in a version controlled application development environment, then try linking outside the version control system. If errors happen only when linking or loading under version control, then check with your version control system vendor for known linker/loader problems.

6.3.2. Duplicate symbols

Duplicate symbol errors usually indicate a programming error. It is invalid to have multiple external function definitions of the same name. The link editor in this case will use the first definition that it encounters, and the result may not be desirable. Change the name of the function or use the static function.

The use of template functions in C++ may generate duplicate symbol errors at link time. This happens when the template is implicitly instantiated in multiple source files. For example:

// t.h
template <class T> class A {
public:
    int f();
};

template <class T> int A<T>::f()
{
    return 55;
}

// file1.C
#include "t.h"
int func();
int main()
{
    A<int> a;
    int obj1 = a.f() + func();
    return obj1;
}
# include "t.h"
int func()
{
    A<int> a;
    int obj2 = a.f();
    return obj2;
}

$ xlC -c file1.C file2.C
file1.C:
file2.C:
$ xlC file1.o file2.o
ld: 0711-224 WARNING: Duplicate symbol:
.A<int>::f()
ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.

Using nm, you will note that the symbol A<int>::f() is defined in both object files:

$ nm -g file1.o
.A<int>::f()           T        100
.func()                U          -
.main                  T          0
A<int>::f()            D        180      12
main                   D        168      12
$ nm -g file2.o
.A<int>::f()           T         68
.func()                T          0
A<int>::f()            D        148      12
func()                 D        136      12

In this case, since the duplicate symbol A<int>::f() has the same definition, it is safe to suppress the link editor message with -bhalt:5:

$ xlC -bhalt:5 file1.C file2.C
file1.C:
file2.C:

The -bhalt link editor option specifies the maximum error level for the linking process to continue, and suppresses any error below the maximum. The recommended solution to fixing this error is to use the -qtemplateregistry compiler option described in 10.5, “Template registry: The preferred method” on page 387, and to take advantage of the improved template handling provided by the VisualAge C++ for AIX Version 6 compiler. See the VisualAge C++ for AIX Compiler Reference, SC09-4959 for details on the option.

6.3.3. Insufficient memory for the linker process

The linker can run out of memory when trying to link very large files. When this happens, linking fails with the following error:

ld: 0711-101 fatal error, allocation of bytes fail in routine initsymtab_info.
There is not enough memory.

This may be because of low paging space or because of low resource limits for the user invoking the command. The AIX linker offers a great deal more functionality than traditional UNIX linkers, but it does require a reasonable amount of virtual memory, particularly when linking large applications with many libraries.

If this type of error is encountered, check the following and increase the space, if necessary:

  • The available paging space on the machine.

  • The resource limits for the user invoking the linker using the ulimit command (see 3.2.6, “Resource limits in 32-bit model” on page 125 for information on how to use the command).

If the problem is not solved by these activities, you may consider running the linker process in the 32-bit large memory model, as explained in 3.2.4, “Using the large and very large memory model” on page 121.

6.3.4. The c++filt utility

The C++ programming language allows function and operator overloading. An overloaded function is a function with the same name as a previously declared function, but with a different parameter list. To distinguish overloaded function names, the compiler uses name mangling to encode the names into unique names so that the link editor will not mistake them as duplicate symbols. The mangled name contains further information about the function and its parameters.

The c++filt utility is provided with the VisualAge C++ for AIX compiler product to convert these mangled names to their original source code names. With the -bloadmap:filename link editor option, function names appearing in the loadmap file, filename, are in mangled form. Use the c++filt utility to get the original function names:

ld: 0711-228 WARNING: Duplicate symbols were found while resolving symbols.
    The following duplicates were found:
 Symbol                    Source-File(Object) OR Import-File{Shared-object}
 ------------------------- -------------------------------------------------
 .f__1AXTi_Fv              file1.C(file1.o)
 ** Duplicate**            file2.C(file2.o)

The c++filt command waits for input from the standard input. If you type in mangled function names, it prints the original functions to the standard output:

$ c++filt
f__1AXTi_Fv
A<int>::f()

To quit the command, type ^D (Control-D).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset