C compilation system

Multiply defined symbols

Multiply defined symbols -- except for different-sized initialized data objects -- are not reported as errors under dynamic linking. The link editor will not report an error for multiple definitions of a function or a same-sized data object when each such definition resides within a different dynamically linked library or within a dynamically linked executable and different dynamically linked libraries. The dynamic linker will use the definition in whichever object occurs first on the cc command line. You can, however, specify -Bsymbolic when you create a dynamically linked library:

cc -dy -K PIC -G -Bsymbolic -o function1.c \
function2.c function3.c

to insure that the dynamic linker uses the dynamically linked library's definition of one of its own symbols, rather than a definition of the same symbol in an executable or another library.

In contrast, multiply defined symbols are generally reported as errors under static linking, because definitions of so-called weak symbols can be hidden from the link editor by a definition of a global symbol. If a defined global symbol exists, the appearance of a weak symbol with the same name does not cause an error.

To illustrate this, our own implementation of the standard C library. This library provides services that users are allowed to redefine and replace. At the same time, however, ANSI C defines standard services that must be present on the system and cannot be replaced in a strictly conforming program. For example, fread(S) is an ANSI C library function; the system function read(S) is not. So a conforming program may redefine read() and still use fread() in a predictable way.

The problem with this is that read() underlies the fread() implementation in the standard C library. A program that redefines read() could ``confuse'' the fread() implementation. To guard against this, ANSI C states that an implementation cannot use a name that is not reserved to it. Therefore _read() -- note the leading underscore -- is used to implement fread() in the standard C library.

Now suppose that a program you have written calls read(). If your program is going to work, the definition for read() has to exist in the C library. It is identical to the definition for _read() and is contained in the same object file.

Suppose further that another program you have written redefines read(), and that this same program calls fread(). Because you get our definitions of both _read() and read() when you usefread(), we would expect the link editor to report the multiply defined symbol read() as an error, and fail to create an executable program. To prevent that, use the #pragma directive in your source code for the library as follows:

   #pragma weak read = _read
Because our read() is defined as a weak symbol, your own definition of read() overrides the definition in the standard C library. You can use the #pragma directive in the same way in your own library code.

There is a second use for weak symbols:

   #pragma weak read
tells the link editor not to complain if it does not find a definition for the weak symbol read. References to the symbol use the symbol value if defined, 0 otherwise. The link editor does not extract archive members to resolve undefined weak symbols. The mechanism is intended to be used primarily with functions. Although it will work for most data objects, it should not be used with uninitialized global data (``common'' symbols) or with data objects in dynamically linked libraries that are exported to executables.
Next topic: Quick-reference guide
Previous topic: Maintenance

© 2003 Caldera International, Inc. All rights reserved.
SCO OpenServer Release 5.0.7 -- 11 February 2003