Неопределенная ссылка на символ в статической библиотеке

Я пытаюсь скомпилировать двоичный файл, связав его со статической библиотекой libfoo.a:

gcc -L. -o myapp myapp.o -lfoo

Но я получаю следующую ошибку от компоновщика:

libfoo.c:101: undefined reference to `_TRACE'

Проблема в том, что у меня нет исходного кода библиотеки libfoo.a. Я попытался получить ссылку на символ _TRACE в библиотеке и получил следующее:

nm libfoo.a | grep TRACE
    U _TRACE

Предполагая, что _TRACE не повлияет на внутреннюю работу в libfoo.a, можно ли заставить компоновщик определить какое-то значение-заполнитель для этого символа, чтобы я мог скомпилировать свой код?


person learning_frog    schedule 23.05.2016    source источник


Ответы (2)


Предполагая, что _TRACE не повлияет на внутреннюю работу в libfoo.a

Это кажется необоснованно обнадеживающим предположением.

Можно ли заставить компоновщик определить какое-то значение заполнителя для этого символа, чтобы я мог скомпилировать свой код?

Первое, что нужно сделать, это проверить документацию libfoo. Статическая библиотека обычно не зависит от символа, который должен определить пользователь; на самом деле такое расположение не работает с традиционными компоновщиками. Я вижу несколько правдоподобных объяснений:

  1. Вам нужно связать какую-то другую (конкретную) библиотеку после libfoo, чтобы предоставить определение для этого символа.

  2. Ожидается, что код, использующий libfoo, будет #include ассоциированным заголовком, и этот заголовок предоставляет предварительное определение _TRACE.

  3. Программы, использующие libfoo, должны быть созданы с использованием определенной цепочки инструментов и, возможно, определенных параметров.

  4. Он просто сломан.

Только в случае (4) уместно попытаться вручную предоставить определение для рассматриваемого символа, и в этом случае лучше всего действовать более или менее так, как в случае (1), путем создания объекта, который предоставляет определение и связывание его после библиотеки. Конечно, это заставляет вас пытаться угадать, каким должно быть определение.

Если _TRACE является глобальной переменной, то определение ее как intmax_t с начальным значением 0 может работать, даже если библиотека ожидает целое число другого размера или с другим знаком. Однако, если предполагается, что это функция, то вы, вероятно, тост. У него может быть слишком много сигнатур, слишком много возможных ожиданий от поведения. Нет оснований думать, что вы могли бы предоставить подходящий заполнитель.

person John Bollinger    schedule 23.05.2016
comment
Если intmax_t _TRACE = 0; не работает, int _TRACE(){ return( 0 ); } может быть так же, как _TRACE может быть макросом, который не был правильно определен, поэтому по умолчанию используется неявно определенная функция, возвращающая int. Однако я сомневаюсь, что когда-нибудь доверю такой библиотеке что-то важное, если такие махинации — это то, что нужно, чтобы заставить ее даже связываться. - person Andrew Henle; 23.05.2016
comment
Моя первоначальная идея была чем-то похожим на #define _TRACE только для компиляции. Я предполагаю, что _TRACE — это функция, которая выводит отладочную информацию, поэтому вполне подойдет заполнитель. Я хотел бы знать, возможно ли это вообще. - person learning_frog; 23.05.2016
comment
@Gustavo - Вы компилируете libfoo.a или у вас есть только сама статическая библиотека? - person Andrew Henle; 23.05.2016
comment
У меня есть только сама статическая библиотека. Я не собираюсь создавать надежный бинарный файл. Я знаю, что это может вызвать серьезные проблемы, я просто хочу знать, возможно ли это. - person learning_frog; 23.05.2016
comment
@Gustavo, компоновщик не видит макросы. Они раскрываются перед компиляцией вашего кода, а тем более связаны. Чтобы удовлетворить неопределенный символ в вашей ссылке, вам необходимо создать ссылку в объектном файле, содержащем соответствующее определение символа. - person John Bollinger; 24.05.2016
comment
@Gustavo, обратите внимание, что это означает, что название вашего вопроса вводит в заблуждение. Ни один символ в вашей библиотеке не соответствует непосредственно макросу в любом исходном файле или заголовке. - person John Bollinger; 24.05.2016

Как я и подозревал, функция _TRACE является своего рода функцией отладки. И я был прав, полагая, что это не повлияет на внутреннюю работу libfoo.a.

Я решил проблему, определяющую функцию _TRACE как:

int _TRACE(char*, ...) { return 0; }

Конечно, это решение временное и не может быть использовано в продакшене, но оно подходит для моих целей компиляции кода.

person learning_frog    schedule 21.06.2016