A weak symbol denotes a specially annotated symbol during linking of Executable and Linkable Format (ELF) object files. By default, without any annotation, a symbol in an object file is strong. During linking, a strong symbol can override a weak symbol of the same name. In contrast, two strong symbols that share a name yield a link error during link-time. When linking a binary executable, a weakly declared symbol does not need a definition. In comparison, (by default) a declared strong symbol without a definition triggers an undefined symbol link error.
Weak symbols are not mentioned by the C or C++ language standards; as such, inserting them into code is not very portable. Even if two platforms support the same or similar syntax for marking symbols as weak, the semantics may differ in subtle points, e.g. whether weak symbols during dynamic linking at runtime lose their semantics or not.
The GNU Compiler Collection and the Solaris Studio C compiler share the same syntax for annotating symbols as weak, namely a special #pragma, #pragma weak
, and, alternatively, a function and variable attribute, __attribute__((weak))
.
The nm command identifies weak symbols in object files, libraries, and executables. On Linux a weak function symbol is marked with "W" if a weak default definition is available, and with "w" if it is not. Weakly defined variable symbols are marked with "V" and "v". On Solaris "nm" prints "WEAK" instead of "GLOB" for a weak symbol.
The following examples work on Linux and Solaris with GCC and Solaris Studio.
main.c:
power_slow.h:
power_slow.c:
power.c:
Build commands:
Output:
When removing the weak attribute and re-executing the build commands, the last one fails with the following error message (on Linux):
The second-last one still succeeds, and ./slow
has the same output.
Taking main.c from the preceding example and adding:
Replacing power_slow.c with:
Build commands: