gcc: Связывание библиотеки C в приложении C приводит к ошибкам «множественного определения»

#c #gcc #multiple-definition-error

#c #gcc #ошибка множественного определения

Вопрос:

У меня есть рабочая библиотека C, которую я хочу связать с приложением на C с помощью gcc, но компоновщик (g ) выдает мне ошибку «множественное определение». С приложением на C и gcc это работает. Все заголовки, определяющие интерфейс, содержат:

 #ifdef __cplusplus 
extern "C" {
#endif
  

Я проверил библиотеку с помощью команды «nm», и в ней действительно есть несколько определений метода (рассматриваемый метод не из общедоступного интерфейса).

Мои вопросы:

  1. Почему моя библиотека имеет несколько определений (у некоторых есть T, а у других — U)?

  2. Почему это работает, если приложение, включающее файл, является приложением на C (я использую -Wall для сборки)?

  3. Нужен ли мне какой-либо специальный атрибут или использовать определенное расширение файла, чтобы это работало, или мне нужно вернуться в школу программирования :)?

Уделяя больше внимания файлу lib.a, я вижу, что один из объектов включен дважды. Например, у меня есть два раздела для одного и того же объекта:

  obj1.o
 00000000     T    Method

 obj2.o
 00000000     T    Hello

 obj1.o
 00000000     T    Method
  

Я предполагаю, что это проблема?

Любая помощь действительно ценится.

Комментарии:

1. Для наглядности. Являются ли множественные символы общедоступным интерфейсом библиотеки (т. Е. Тем, что находится в файлах заголовков) или из стандартного содержимого библиотеки?

2. Вы создаете со всеми одинаковыми настройками? Несколько настроек приведут к несовместимости двоичных файлов — т. Е. соглашения о вызовах по умолчанию и тому подобное.

3. Для Laserallan — хороший вопрос. Повторяющиеся символы взяты из стандартной библиотеки.

4. Для Билли Онеала — Да, те же настройки, просто используются -I и -L, ничего особенного.

5.Где вы используете gcc и / или g при создании приложения на C ? Предположим, у вас есть исходные файлы cLib.c cApp.c и cppApp.cpp . Если вы попробуете это, я полагаю, это сработает? gcc cLib.c -o cLib.o; gcc cApp.c -o cApp.o; gcc cLib.o cApp.o -o cApp.exe Но это не удается?: gcc cLib.c -o cLib.o; g cppApp.cpp -o cppApp.o; g cLib.o cppApp.o -o cppApp.exe

Ответ №1:

Мое дикое предположение заключается в том, что «#define BLAHBLAH_H» и «#ifndef BLAHBLAH_H / #endif» устанавливаются за пределами ‘extern «C»{}’.

Комментарии:

1. Слишком дико 🙂 методы, о которых идет речь, не являются общедоступными, поэтому их заголовки не нуждаются во внешнем C. (по крайней мере, насколько я знаю).

2. Я не очень хорошо разбираюсь в cpp. Однако в C ключевое слово extern просто означает, что переменная / функция объявлена где-то и, следовательно, она объявляется локально без указания фактического определения. Если больше ничего не работает, возможно, стоит попробовать. 😛 Я с нетерпением жду реальной причины и решения.

Ответ №2:

поиграв, я обнаружил, что фактически вся командная строка (это своего рода сложное приложение с автоматической компиляцией и компоновкой) содержала параметр —whole-archive перед включением библиотеки C. Перемещение библиотеки после —no-whole-archive устранило проблему.

Исходная команда

    gcc -Wl,**--whole-archive** -l:otherlibs *-Llibpath -l:libname* Wl,**--no-whole-archive** -o myApp hello.c
  

Исправлена команда

    gcc -Wl,**--whole-archive** -l:otherlibs Wl,**--no-whole-archive** *-Llibpath -l:libname* -o myApp hello.c
  

Спасибо всем за помощь, ребята, и извините, если я не предоставил достаточной / точной информации.

С наилучшими пожеланиями