Контекст: я могу создать библиотеку общих объектов, которая без проблем работает на 32-битной Linux. Когда я пытаюсь сделать то же самое на 64-битной Linux, я вижу эту ошибку компоновщика:
Эта ошибка довольно распространена в Интернете. Решение состоит в том, чтобы скомпилировать статически связанную библиотеку с позиционно-независимым кодом (-fPIC).
Я не понимаю, почему это не требуется для 32-битной сборки. Кто-нибудь может помочь?
Ок, ответ подробно описан здесь: http://www.technovelty.org/code/c/amd64-pic.html.
Суть объяснения в том, что архитектура i386 неявно разыменовывает указатель кадра для каждой функции (объясняется в последнем абзаце страницы по ссылке). Этот процесс влечет за собой некоторые дополнительные накладные расходы, поэтому в новых 64-битных архитектурах эти накладные расходы на разыменование были устранены в качестве оптимизации.
Следствием этой оптимизации с точки зрения связывания стало то, что если 64-битный код явно не скомпилирован как позиционно-независимый, он будет производить код, жестко закодированный со смещениями для своего контекста выполнения.
Это несовершенное объяснение содержания страницы по ссылке, но для моих целей его достаточно.
«Независимый от позиции код» всегда требуется, если ваш объектный модуль будет использоваться в разделяемой библиотеке. Это сильно зависит от платформы и влечет за собой некоторые накладные расходы.
Причина, по которой вы должны явно указывать его на amd64, но не на x386, заключается просто в том, что он используется по умолчанию для x86, но не для amd64.
Также обратите внимание на разницу между "-fpic" и "-fPIC":
-fpic
Generate position-independent code (PIC) suitable for use in a
shared library, if supported for the target machine. Such code
accesses all constant addresses through a global offset table
(GOT). The dynamic loader resolves the GOT entries when the pro-
gram starts (the dynamic loader is not part of GCC; it is part
of the operating system). If the GOT size for the linked execu-
table exceeds a machine-specific maximum size, you get an error
message from the linker indicating that -fpic does not work; in
that case, recompile with -fPIC instead. (These maximums are 8k
on the SPARC and 32k on the m68k and RS/6000. The 386 has no
such limit.)
Position-independent code requires special support, and there
fore works only on certain machines. For the 386, GCC supports
PIC for System V but not for the Sun 386i. Code generated for
the IBM RS/6000 is always position-independent.
When this flag is set, the macros __pic__ and __PIC__ are defined to 1.
-fPIC
If supported for the target machine, emit position-independent
code, suitable for dynamic linking and avoiding any limit on the
size of the global offset table. This option makes a difference
on the m68k, PowerPC and SPARC.
Position-independent code requires special support, and therefore
works only on certain machines.
When this flag is set, the macros __pic__ and __PIC__ are defined to 2.