#c
#c
Вопрос:
Контекст: я изучаю C по ходу работы, и я нахожусь в точке, где я обнаруживаю, что не могу связать свой проект. Я также нахожу, что диагностика C не самая лучшая, когда дело доходит до точного определения проблем. (Или, по крайней мере, не лучший, учитывая мои знания.)
Я вижу много вопросов StackOverflow по этому поводу, но очень сложно обобщить, если ситуация не соответствует вашему конкретному коду.
Контекст проекта: у меня есть такой проект:
src
zmachine
main.c
zmachine.h
terp_cheap
terp.cheap.c
terp_cheap.h
В каждом из этих каталогов создается статическая библиотека. Затем у меня есть шаг связывания, который берет .a
файлы библиотеки и связывает их с исполняемым файлом.
Проблема: все было хорошо, пока я не добавил структуру. Как только я это сделал, при сборке всего проекта этап связывания завершается неудачей:
COMPLETE: Z-Machine architecture built.
COMPLETE: Cheap Interface built.
gcc -o quendorc build/zmachine.a build/terp_cheap.a
Undefined symbols for architecture x86_64:
"_quendor_startup", referenced from:
_terp_process_arguments in terp_cheap.a(terp_cheap.o)
ld: symbol(s) not found for architecture x86_64
Ошибка говорит мне, что я не определил символы (я думаю, это: _quendor_startup
), но, насколько я могу судить, у меня есть.
_quendor_startup
То, на что он ссылается, определено в zmachine.h
:
typedef struct quendor_startup_struct {
char *story_file;
} quendor_startup_t;
extern quendor_startup_t quendor_startup;
Обратите внимание, что я также добавляю его туда как quendor_startup
.
Основной файл в этой библиотеке ( main.c
) также имеет внешний:
extern quendor_startup_t quendor_startup;
Хотя я даже не уверен, нужно ли мне это. Все это является библиотекой zmachine. Теперь перейдем к библиотеке terp_cheap.
Два файла в этой библиотеке terp_cheap.h
и terp_cheap.c
также имеют внешний:
extern quendor_startup_t quendor_startup;
terp_cheap
Библиотека — это та, с которой компоновщик, похоже, говорит, что проблема. Итак, учитывая вышесказанное, я не уверен, почему это так. Я должен отметить, что включаемый файл для terp_cheap
библиотеки ссылается на zmachine.h
включение:
#include "../zmachine/zmachine.h"
Таким образом, на структуру в zmachine
должна быть возможность ссылаться в terp_cheap
библиотеке. То есть я не знаю, куда еще я мог бы поместить внешние файлы.
То, как я использую эту структуру, находится в terp_cheap.c
файле, подобном этому:
void terp_process_arguments( int argc, char *argv[] ) {
...
quendor_startup.story_file = strdup(argv[optind]);
printf("Loading %s.n", quendor_startup.story_file);
...
}
Обратите внимание, что эти строки находятся в terp_process_arguments()
функции, на которую, похоже, ссылается мой сбой компоновщика.
Итак, что я не вижу, как здесь сделать, так это эффективно диагностировать, почему это происходит. Я знаю, что, по мнению компоновщика, отсутствует. Чего я не понимаю, так это почему он считает, что он отсутствует, учитывая то, что я определил выше.
Вероятна ли ситуация, когда я где-то пропускаю extern? Или, возможно, мое действие ссылки настроено неправильно? Или моя структура выполнена неправильно?
Ответ №1:
На самом деле вы не определили рассматриваемую переменную.
Когда вы делаете это:
extern quendor_startup_t quendor_startup;
У вас есть объявление, означающее, что вы говорите, что переменная где-то существует. Сбой происходит при связывании, потому что это объявление не может быть разрешено.
Вам нужно определить его ровно в одном исходном файле следующим образом:
quendor_startup_t quendor_startup;
Учитывая, что у вас есть объявление в zmachine / zmachine.h, было бы разумно поместить определение в zmachine /main.c . Кроме того, вам не нужно явно добавлять это объявление в другое место, если исходный файл, которому оно требуется, включает zmachine.h .
Комментарии:
1. АХ! Это то, чего мне не хватало. Я понял. В принципе, я поместил эту строку (
quendor_startup_t quendor_startup;
) в свойmain.c
файл, и все работало нормально. И, да, я только начал задаваться вопросом, не злоупотреблял ли яextern
в этом случае. Спасибо за помощь!