web-dev-qa-db-fra.com

Erreurs "Plusieurs définitions", "premier défini ici"

J'ai 3 projets: Server, Client et Commons. Faire des paires en-tête et source dans Commons ne pose aucun problème et je peux accéder librement aux fonctions à partir de Server et de Client.

Cependant, pour une raison quelconque, créer des fichiers source/en-tête supplémentaires dans les projets Server ou Client provoque toujours des erreurs multiple definition of (...) et first defined here.

Exemple:

commands.h (dans le répertoire racine du projet Client)

#ifndef COMMANDS_H_
#define COMMANDS_H_

#include "commands.c"

void f123();

#endif /* COMMANDS_H_ */

Commandes.c (dans le répertoire racine du projet Client)

void f123(){

}

main.c (dans le répertoire racine du projet Client)

#include "commands.h"
int main(int argc, char** argv){

}

Les erreurs:

make: *** [Client] Error 1      Client
first defined here              Client
multiple definition of `f123'   commands.c

Nettoyer, reconstruire l’index, reconstruire des projets n’aide pas. Le redémarrage de l'ordinateur non plus.

13
matt-pielat

Le problème ici est que vous incluez commands.c dans commands.h avant le prototype de fonction. Par conséquent, le préprocesseur C insère le contenu de commands.c dans commands.h avant le prototype de fonction. commands.c contient la définition de la fonction. En conséquence, la définition de la fonction se termine avant la déclaration de la fonction à l'origine de l'erreur.

Le contenu de commands.h après la phase de pré-traitement ressemble à ceci:

#ifndef COMMANDS_H_
#define COMMANDS_H_

// function definition
void f123(){

}

// function declaration
void f123();

#endif /* COMMANDS_H_ */

Ceci est une erreur car vous ne pouvez pas déclarer une fonction après sa définition en C. Si vous permutez #include "commands.c" et la déclaration de fonction, l'erreur ne devrait pas se produire car, à présent, le prototype de fonction précède la déclaration de fonction. 

Cependant, inclure un fichier .c est une mauvaise pratique et doit être évité. Une meilleure solution à ce problème consisterait à inclure commands.h dans commands.c et à lier la version compilée de la commande au fichier principal. Par exemple:

commands.h

ifndef COMMANDS_H_
#define COMMANDS_H_

void f123(); // function declaration

#endif

orders.c

#include "commands.h"

void f123(){} // function definition
16
Giuseppe Pes

Vous ne devez pas inclure commandes.c dans votre fichier d'en-tête. En général, vous ne devez pas inclure de fichiers .c. Commandes.c devrait plutôt inclure commands.h. Tel que défini ici, le préprocesseur C insère le contenu de commandes.c dans commandes.h où figure l'inclusion. Vous vous retrouvez avec deux définitions de f123 dans commands.h.

commands.h

#ifndef COMMANDS_H_
#define COMMANDS_H_

void f123();

#endif

orders.c

#include "commands.h"

void f123()
{
    /* code */
}
4
andrewrmack

Peut-être avez-vous inclus le fichier .c dans le fichier Make plusieurs fois. 

1
Chuanhang.gu

J'ajoute ceci A parce que je me suis fait prendre avec une version bizarre de ce qui m'a vraiment fait me gratter la tête pendant environ une heure, jusqu'à ce que je découvre la cause première. Ma charge échouait à cause de plusieurs répétitions de ce format

<path>/linit.o:(.rodata1.libs+0x50): multiple definition of `lua_lib_BASE'
<path>/linit.o:(.rodata1.libs+0x50): first defined here

Je me suis avéré être un bogue dans ma magie Makefile où j'avais une liste de fichiers C et utilisant vpath, etc., de sorte que les compilations les récupéraient dans le bon répertoire dans la hiérarchie. Cependant, un fichier C a été répété dans la liste, à la fin d'une ligne et au début de la suivante, de sorte que la charge gcc générée par la marque ait le fichier .o deux fois sur la ligne de commande. Durrrrh. Les définitions multiples provenaient de plusieurs occurrences du même fichier. L'éditeur de liens a ignoré les doublons en dehors des initialiseurs statiques! 

0
TerryE