Ошибки "множественного определения", "впервые определены здесь"
У меня есть 3 проекта: сервер, клиент и сообщество. Создание папок заголовка и источника в Commons не вызывает никаких проблем, и я могу свободно обращаться к функциям от сервера и клиента.
Однако по некоторым причинам создание дополнительных файлов источника/заголовка в проекте Server или Client всегда вызывает ошибки multiple definition of (...)
и first defined here
.
Пример:
commands.h (в корневом каталоге проекта Client)
#ifndef COMMANDS_H_
#define COMMANDS_H_
#include "commands.c"
void f123();
#endif /* COMMANDS_H_ */
commands.c (в корневом каталоге проекта Client)
void f123(){
}
main.c (в корневом каталоге проекта Client)
#include "commands.h"
int main(int argc, char** argv){
}
Ошибки:
make: *** [Client] Error 1 Client
first defined here Client
multiple definition of `f123' commands.c
Очистка, восстановление индекса, восстановление проектов не помогают. Не перезагружает компьютер.
Ответы
Ответ 1
Проблема здесь в том, что вы включаете commands.c
в commands.h
перед прототипом функции. Следовательно, препроцессор C вставляет содержимое commands.c
в commands.h
перед прототипом функции. commands.c
содержит определение функции. В результате определение функции заканчивается раньше, чем объявление функции, вызывающее ошибку.
Содержимое commands.h
после фазы препроцессора выглядит так:
#ifndef COMMANDS_H_
#define COMMANDS_H_
// function definition
void f123(){
}
// function declaration
void f123();
#endif /* COMMANDS_H_ */
Это ошибка, потому что вы не можете объявить функцию после ее определения в C. Если вы поменяли местами #include "commands.c"
и объявление функции, ошибка не должна произойти, потому что теперь прототип функции предшествует объявлению функции,
Тем не менее, включение файла .c
является плохой практикой и его следует избегать. Лучшим решением для этой проблемы было бы включить commands.h
в commands.c
и связать скомпилированную версию команды с основным файлом. Например:
commands.h
#ifndef COMMANDS_H_
#define COMMANDS_H_
void f123(); // function declaration
#endif
commands.c
#include "commands.h"
void f123(){} // function definition
Ответ 2
Вы не должны включать command.c в свой файл заголовка. В общем, вы не должны включать файлы .c. Скорее, command.c должен включать команды .h. Как определено здесь, препроцессор C вставляет содержимое команд .c в команды .h, где включено. Вы получаете два определения f123 в командах .h.
commands.h
#ifndef COMMANDS_H_
#define COMMANDS_H_
void f123();
#endif
commands.c
#include "commands.h"
void f123()
{
/* code */
}
Ответ 3
Возможно, вы включили файл .c
в make файл несколько раз.
Ответ 4
Я добавляю это А, потому что я попался с причудливой версией этого, которая действительно заставила меня почесывать голову около часа, пока я не заметил основную причину. Моя загрузка терпела неудачу из-за многократного повторения этого формата
<path>/linit.o:(.rodata1.libs+0x50): multiple definition of `lua_lib_BASE'
<path>/linit.o:(.rodata1.libs+0x50): first defined here
Я оказался ошибкой в магии Makefile, где у меня был список файлов C и использование vpath и т.д., поэтому компиляторы выберут их из правильного каталога в иерархии. Однако один файл C был повторен в списке, в конце одной строки и в начале следующего, поэтому загрузка gcc, сгенерированная make, имела файл .o
дважды в командной строке. Durrrrh. Несколько определений были получены из нескольких экземпляров одного и того же файла. Компилятор игнорировал дубликаты, кроме статических инициализаторов!