Collective Wisdom from the Experts 107
So, let’s say the linker is saying def is defined more than once. Many program-
ming languages, such as C, C++, and D, have both declarations and defini-
tions. Declarations normally go into header files, like:
extern int iii;
which generates an external reference to the symbol iii. A definition, on the
other hand, actually sets aside storage for the symbol, usually appears in the
implementation file, and looks like this:
int iii = 3;
How many definitions can there be for each symbol? As in the film Highlander,
there can be only one. So, what if a definition of iii appears in more than one
implementation file?
// File a.c
int iii = 3;
// File b.c
double iii(int x) { return 3.7; }
The linker will complain about iii being multiply defined.
Not only can there be only one, there must be one. If iii appears only as a
declaration, but never a definition, the linker will complain about iii being an
unresolved symbol.
To determine why an executable is the size it is, take a look at the map file
that linkers optionally generate. A map file is nothing more than a list of all
the symbols in the executable, along with their addresses. This tells you what
modules were linked in from the library, and the sizes of each module. Now
you can see where the bloat is coming from. Often, there will be library mod-
ules that you have no idea why were linked in. To figure it out, temporarily
remove the suspicious module from the library, and relink. The undefined
symbol error then generated will indicate who is referencing that module.
Although it is not always immediately obvious why you get a particular
linker message, there is nothing magical about linkers. The mechanics are
straightforward; it’s the details you have to figure out in each case.