IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Multiple definition error (link)


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Points : 68
    Points
    68
    Par défaut Multiple definition error (link)
    Bonjour,

    il semblerait que c'est un problème classique mais :

    1. je ne comprends pas pourquoi j'ai ce problème
    2. je n'arrive pas à solutionner mon problème

    Donc voici ce que je fais. J'ai un fichier header dont plusieur .c se servent. J'ai pour chacun de mes blocs de variables définit des conditions comme l'indique ce tuto : http://melem.developpez.com/langagec/objc/
    en dessous de l'erreur une partie du code.
    et pourtant j'ai l'erreur suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    ./demo2.o:(.data+0x8): multiple definition of `affiche_magnifique'
    ./demo1.o:(.data+0x8): first defined here
    ./demo2.o:(.data+0x4): multiple definition of `sourisCapteur'
    ./demo1.o:(.data+0x4): first defined here
    ./demo2.o:(.bss+0x0): multiple definition of `demo_index'
    ./demo1.o:(.bss+0x0): first defined here
    ./demo2.o:(.data+0x0): multiple definition of `demo_max'
    ./demo1.o:(.data+0x0): first defined here
    ./demo2.o:(.bss+0x4): multiple definition of `ticks'
    ./demo1.o:(.bss+0x4): first defined here
    ./demo2.o:(.bss+0x8): multiple definition of `timer'
    ./demo1.o:(.bss+0x8): first defined here
    ./demo2.o:(.bss+0xc): multiple definition of `fullscreen'
    ./demo1.o:(.bss+0xc): first defined here
    ./demo3.o:(.data+0x8): multiple definition of `affiche_magnifique'
    ./demo1.o:(.data+0x8): first defined here
    ./demo3.o:(.data+0x4): multiple definition of `sourisCapteur'
    ./demo1.o:(.data+0x4): first defined here
    ./demo3.o:(.bss+0x0): multiple definition of `demo_index'
    ./demo1.o:(.bss+0x0): first defined here
    ./demo3.o:(.data+0x0): multiple definition of `demo_max'
    ./demo1.o:(.data+0x0): first defined here
    ./demo3.o:(.bss+0x4): multiple definition of `ticks'
    ./demo1.o:(.bss+0x4): first defined here
    ./demo3.o:(.bss+0x8): multiple definition of `timer'
    ./demo1.o:(.bss+0x8): first defined here
    ./demo3.o:(.bss+0xc): multiple definition of `fullscreen'
    ./demo1.o:(.bss+0xc): first defined here
     
     
    [..]
     
     
    ./demo1.o:(.bss+0xc): first defined here
    ./demo4.o:(.data+0x8): multiple definition of `affiche_magnifique'
    ./demo1.o:(.data+0x8): first defined here
    ./main.o:(.bss+0xc): multiple definition of `fullscreen'
    ./demo1.o:(.bss+0xc): first defined here
    ./main.o:(.bss+0x0): multiple definition of `demo_index'
    ./demo1.o:(.bss+0x0): first defined here
    ./main.o:(.data+0x4): multiple definition of `sourisCapteur'
    ./demo1.o:(.data+0x4): first defined here
    ./main.o:(.data+0x0): multiple definition of `demo_max'
    ./demo1.o:(.data+0x0): first defined here
    ./main.o:(.data+0x8): multiple definition of `affiche_magnifique'
    ./demo1.o:(.data+0x8): first defined here
    ./main.o:(.bss+0x4): multiple definition of `ticks'
    ./demo1.o:(.bss+0x4): first defined here
    ./main.o:(.bss+0x8): multiple definition of `timer'
    ./demo1.o:(.bss+0x8): first defined here

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    #ifndef H_VAR
     
    #define H_VAR
    int demo_index = 0, 			// Index de la demo en cours
        demo_max   = 4, 			// Nombre de démos maximum
        ticks      = 0,			// Variable de temps pour le moteur physique
        timer      = 0;			// Timer 1
     
    #endif
     
     
    GLuint texID[2];			// buffer pour la texture
     
    int X_pos,
        Y_pos;				// position de la souris
     
     
    #ifndef H_PAR
     
    #define H_PAR
     
    int sourisCapteur      = 1,		// Choix entre le mode souris et le mode capteurs
        fullscreen         = 0,		// Mode plein ecran
        affiche_magnifique = 1;		// Choix d'afficher le logo ou non
     
    #endif
     
     
     
    float capteur_norm[NB_CAPTEURS+1];	// donnees des faux capteurs normalisees (pour le mode souris)
    et je n'ai aucun souci avec et et
    Je ne comprends pas
    Pour aider, voici le fichier de sh de mon build.sh :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    gcc -c -O3 -std=gnu99 -ffast-math src/cp*.c src/chipmunk.c ./*.c -Isrc
    g++ -c maincpp.cpp usbdevice.cxx
    g++ -O3 -std=gnu99 -ffast-math ./*.o -Isrc -lglut  -lpng -lusb -lpthread -o alldemos
    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par SpongeBob Voir le message
    Pour aider, voici le fichier de sh de mon build.sh :
    poste l'ensemble de ton code, parce que ce que tu as fourni est insuffisant.

  3. #3
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Bonjour,
    Au premier abord, j'aurais tendance à dire que si tu inclus ce .h dans plusieurs .c, et bien, tu vas te retrouver avec autant d'instances de tes variables. Il faudrait plutôt faire quelque chose de ce goût là (code à la levé donc excuser si il y a qqs erreurs et certainement perfectible):
    var.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    #ifndef H_VAR
     #define H_VAR
     
    #ifdef _VAR_IMPL_
    #define _VAR_H_SCOPE_
    #else /*  _VAR_IMPL_ */
    #define  _VAR_H_SCOPE_ extern
    #endif /*  _VAR_IMPL_ */
     
    _VAR_H_SCOPE_ int demo_index 
    #ifdef _VAR_IMPL_
           = 0
    #endif
    ;
    etc...
    Puis un var.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #define _VAR_IMPL_
    #include var.h
    Dans les autres .c:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /* pas de définition de _VAR_IMPL_ */
    #include var.h

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Points : 68
    Points
    68
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Bonjour,
    Au premier abord, j'aurais tendance à dire que si tu inclus ce .h dans plusieurs .c, et bien, tu vas te retrouver avec autant d'instances de tes variables. Il faudrait plutôt faire quelque chose de ce goût là (code à la levé donc excuser si il y a qqs erreurs et certainement perfectible):
    var.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    #ifndef H_VAR
     #define H_VAR
     
    #ifdef _VAR_IMPL_
    #define _VAR_H_SCOPE_
    #else /*  _VAR_IMPL_ */
    #define  _VAR_H_SCOPE_ extern
    #endif /*  _VAR_IMPL_ */
     
    _VAR_H_SCOPE_ int demo_index 
    #ifdef _VAR_IMPL_
           = 0
    #endif
    ;
    etc...
    Puis un var.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #define _VAR_IMPL_
    #include var.h
    Dans les autres .c:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /* pas de définition de _VAR_IMPL_ */
    #include var.h
    Hum, tout ceci me parraît bien compliqué. Je vais tout de même essayer mais avant je poste une partie de l'ensemble (le tout étant beaucoup trop gros)
    Merci

  5. #5
    Scorpi0
    Invité(e)
    Par défaut
    Voici un article qui m'avait beaucoup aidé lorsque j'avais des problèmes de définitions multiple :

    http://www.gamedev.net/reference/art...rticle1798.asp

    Essaye de voir si tu rentre dans l'un des cas, l'auteur explique comment s'en sortir !!

    Ton problème est certainement le numéro 4 (qui est le plus vicieux).
    Tu déclares une variable dans un header, puis tu inclus ce header 2 fois dans 2 fichiers c séparé.

    Bien que tu aie les bloc ifdef, define et endif, ça n'empêche pas le compilateur de planter. chaque fichier *.o sera correctement crée, mais chacun aura sa propre variable affiche_magnifique. En effet, les bloc ifdef, define et endif n'agisse seulement à la compilation de l'objet, et non pas sur le projet global.

    Tu a donc un fichier objet1.o avec une variable affiche_magnifique, et un fichier objet2.o avec aussi une variable nommée affiche_magnifique.
    Au moment de créer l'exécutable, le compilateur te dis logiquement qu'il existe deux fois la variable affiche_magnifique, et qu'il ne sait pas laquelle est la bonne.

    Extrait :

    Notice how there are two copies of "my_global" in that final block. Although "my_global" was unique for each translation unit (this would be assured by the use of the inclusion guards), combining the object files generated from each translation unit would result in there being more than one instance of my_global in the file. This is flagged as an error, as the linker has no way of knowing whether these two identifiers are actually same one, or if one of them was just misnamed and they were actually supposed to be 2 separate variables. So you have to fix it.

    The answer is not to define variables or functions in headers. Instead, you define them in the source files where you can be sure that they will only get compiled once (assuming you don't ever #include any source files, which is a bad idea for exactly this reason). This gives you a new problem: how do you make the functions and variables globally visible if they aren't in a common header any more? How will other files "see" them? The answer is to declare the functions and variables in the header, but not to define them. This lets the compiler know that the function or variable exists, but delegates the act of resolving the address to the linker.

    To do this for a variable, you add the keyword 'extern' before its name:

    extern int my_global;

    The 'extern' specifier is like telling the compiler to wait until link time to resolve the 'connection'. And for a function, you just put the function prototype:

    int SomeFunction(int parameter);

    Functions are considered 'extern' by default so it is customary to omit the 'extern' in a function prototype.


    En résumé, en ajoutant 'extern' devant les variables de ton header, ça devrait fonctionner.
    Le extern dira au compilateur : si tu vois plusieurs fois une déclaration de variable extern, ne panique pas, attend l'exécution et la première à venir sera la bonne (enfin, si j'ai bien compris l'article ^^).


    Edit : maintenant sur ton code, utiliser ces variables globales n'est certainement pas une bonne chose en général. Essayes de voir si tu peux t'en passer, au pire, utilise des defines, des enums, mais des variables globales lâchées comme ça dans un header, je trouve ça particulièrement moche ^^

    Edit2 : au passage, l'article que tu as fournis (ici) en parle :

    I-B. Le mot-clé extern
    En langage C, tout objet (variable ou fonction) doit toujours avoir été déclaré avant d'être utilisé. Nous avons déjà résolu le problème pour les fonctions, ne reste donc plus que les variables. Supposons donc que l'on souhaite, depuis un fichier donné, accéder à une variable globale définie dans un autre fichier. On ne peut pas tout simplement déclarer une deuxième fois la variable car on aurait alors deux variables de même nom au sein d'un même projet ce qui conduirait à une erreur lors de l'édition des liens. Le mot-clé extern permet de résoudre le problème. Placé devant une déclaration, il permet d'indiquer que la variable ou fonction est définie (plus précisément : peut être définie) dans un autre fichier (source ou compilé). Evidemment si l'objet déclaré est une fonction, ce mot-clé ne sert qu'à la déco !


    Tu es sûr de bien l'avoir lu ?
    Dernière modification par Scorpi0 ; 14/08/2008 à 12h37.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Points : 68
    Points
    68
    Par défaut
    En effet le fait de définir mes variables :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int sourisCapteur      = 1,		// Choix entre le mode souris et le mode capteurs
        fullscreen         = 0,		// Mode plein ecran
        affiche = 1;		// Choix d'afficher le logo ou non
     
    int demo_index = 0, 			// Index de la demo en cours
        demo_max   = 4, 			// Nombre de démos maximum
        ticks      = 0,			// Variable de temps pour le moteur physique
        timer      = 0;			// Timer 1
    dans le main.c et de mettre dans mon definition.h, un extern devant ces définitions m'a permit de pallier au problème. Néanmoins cette solution me parraÎt salle ? La solution proposé plus haut n'a pas encore été testé, mais elle me parrassait plus propre.

    Pour eclaircir un peu, j'ai dans mon main.c des variables globales, utilisées par d'autres fonctions contenues dans d'autres fichiers .c
    Prenons exemple avec , je l'utilise dans demo1.c demo2.c et demo3.c et dans le main.c
    Je mets donc dans mon definition.h que j'inclus dans demo1.c, demo2.c, demo3.c et definition.h

    De même, j'ai demo4.c qui inclus definition.h dans lequel se trouve x_pos. et dans main.c j'ai aussi inclus mon definition.h et là aucun besoin de mettre extern, c'est cela que je ne comprends pas..
    Merci encore

  7. #7
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par SpongeBob Voir le message
    En effet le fait de définir mes variables :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int sourisCapteur      = 1,		// Choix entre le mode souris et le mode capteurs
        fullscreen         = 0,		// Mode plein ecran
        affiche = 1;		// Choix d'afficher le logo ou non
     
    int demo_index = 0, 			// Index de la demo en cours
        demo_max   = 4, 			// Nombre de démos maximum
        ticks      = 0,			// Variable de temps pour le moteur physique
        timer      = 0;			// Timer 1
    dans le main.c et de mettre dans mon definition.h, un extern devant ces définitions m'a permit de pallier au problème. Néanmoins cette solution me parraÎt salle ? La solution proposé plus haut n'a pas encore été testé, mais elle me parrassait plus propre.
    Ce qui est sale, c'est d'utiliser des variables globales. Mais si tu y tiens, il faut le faire correctement :

    http://emmanuel-delahaye.developpez....s.htm#globales

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Points : 68
    Points
    68
    Par défaut
    OK,
    merci. On peut dire que c'est résolu !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Link & multiple definition
    Par Pece_ dans le forum Langage
    Réponses: 12
    Dernier message: 02/07/2011, 14h30
  2. Error multiple definition
    Par guilermo dans le forum Débuter
    Réponses: 4
    Dernier message: 29/09/2009, 14h36
  3. multiple definition of operator<<...
    Par kleenex dans le forum C++
    Réponses: 3
    Dernier message: 05/05/2006, 03h56
  4. [LG]Interfaces et multiples définitions
    Par fatt dans le forum Langage
    Réponses: 2
    Dernier message: 15/04/2004, 23h41
  5. multiple definition
    Par scorbo dans le forum C
    Réponses: 5
    Dernier message: 10/09/2003, 14h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo