2011-06-24 5 views
33

DebugUtil.hUn ou plusieurs symboles se multiplient définis trouvés

#ifndef DEBUG_UTIL_H 
#define DEBUG_UTIL_H 

#include <windows.h> 

int DebugMessage(const char* message) 
{ 
    const int MAX_CHARS = 1023; 
    static char s_buffer[MAX_CHARS+1]; 

    return 0; 
} 

#endif 

Lorsque je tente d'exécuter ce que je reçois cette erreur:

Terrain.obj : error LNK2005: "int __cdecl DebugMessage(char const *)" ([email protected]@[email protected]) already defined in Loodus.obj

Renderer.obj : error LNK2005: "int __cdecl DebugMessage(char const *)" ([email protected]@[email protected]) already defined in Loodus.obj

test.obj : error LNK2005: "int __cdecl DebugMessage(char const *)" ([email protected]@[email protected]) already defined in Loodus.obj

C:\Users\Tiago\Desktop\Loodus Engine\Debug\Loodus Engine.exe : fatal error LNK1169: one or more multiply defined symbols found

Mais pourquoi cela se produit? Mettez #ifndef #define et #endif dans l'en-tête afin que plusieurs définitions ne se produisent pas

+0

possible doublon de [Erreur de liaison avec des fonctions très simples C++ sur le fichier .h] (http://stackoverflow.com/questions/6424911/link-error-with-really-functions-s-f-c-on-h-file) –

+0

@ Armen: C'est comme Hame que les réponses sur _this_ question sont beaucoup mieux :( –

Répondre

54

Placez la définition (body) dans un fichier cpp et ne conservez que la déclaration dans un fichier h. Inclure les gardes opérer seulement dans une unité de traduction (fichier source alias), pas dans l'ensemble de votre programme.

La règle de définition unique de la norme C++ indique qu'il doit exister exactement une définition de chaque fonction non intégrée utilisée dans le programme. Donc, une autre alternative serait de rendre votre fonction inline.

+2

J'ai le même problème. J'ai des valeurs constantes dans un espace de noms dans mon fichier d'en-tête. C'est une bibliothèque de maths donc je les ai soulignés mais qu'en est-il des valeurs constantes? –

+0

@ CahitBurakKüçüksütcü: les variables constantes ont une liaison interne; –

+0

OMFG DONNEZ-MOI VOTRE F-ING PAYPALL ILL VOUS DONNEZ BEAUCOUP D'ARGENT MFKR – Acidic

10

Faites la fonction inline ou déclarez la fonction dans un fichier d'en-tête et définissez-la dans un fichier cpp.

inline int DebugMessage(const char* message) 
{ 
    const int MAX_CHARS = 1023; 
    static char s_buffer[MAX_CHARS+1]; 

    return 0; 
} 

EDIT:

Comme un commentaire par Tomalak Geret'kal suggère, il est préférable d'utiliser mes dernières suggestions que mon ancien et déplacer la déclaration de la fonction dans un fichier cpp.

+2

'inline'ing est quelque chose à penser quand vous voulez inline la fonction, pas quelque chose que vous utiliser pour pirater une erreur de compilation parce que vous ne comprenez pas ce qui se passe. –

+0

@Tomalak Geret'kal: Je suis d'accord que c'est le cas et je ne le fais généralement pas, mais cela peut être pratique si c'est une petite fonction que vous allez utiliser dans votre programme. – GWW

+0

Et c'est bien. De tels critères manquaient dans votre réponse, cependant. –

0

Déplacez la définition vers un fichier .cpp. Déclarez vos fonctions dans des fichiers C++.

0

Puisque vous avez défini votre fonction dans le fichier d'en-tête et que ce fichier d'en-tête est inclus depuis plusieurs fichiers sources, il est défini pour chaque fichier source qui l'inclut. C'est pourquoi il est signalé comme étant défini à plusieurs endroits.

Alternativement, vous pourriez le faire en ligne de sorte que le code soit inséré partout où il est utilisé au lieu d'être défini comme une fonction distincte à chaque fois.

0

Il semble que vous incluiez DebugUtil.h dans plus d'une unité de traduction, puis que vous liez ces objets ensemble. Cependant, DebugUtil.h fournit une définition pour la fonction DebugMessage, de sorte que la définition existe dans toutes les unités de traduction qui ont incorporé l'en-tête. Par conséquent, lorsque vous liez les objets, l'éditeur de liens se plaint à juste titre que le symbole soit défini plusieurs fois.

Modifiez DebugUtil.h afin qu'il déclare DebugMessage via un prototype, mais ne fournit pas de définition et placez la définition de DebugMessage dans un fichier .c que vous compilerez et liez avec vos autres objets.

0

Cela empêche uniquement les inclusions multiples dans le même fichier source; plusieurs fichiers source #include il générera encore plusieurs définitions de DebugMessage(). En général, vous ne devriez pas du tout placer les fonctions dans les fichiers d'en-tête ou les rendre static (et généralement inline, car sinon, il n'est généralement pas logique d'avoir plusieurs définitions static de la même fonction).

3

Cette fonction est incluse dans chaque unité de traduction et, par conséquent, vous obtenez plusieurs définitions de celle-ci - chaque fichier .obj contient sa propre copie. Quand il est temps de les lier tous ensemble, l'éditeur de liens affiche correctement l'erreur ci-dessus.

Vous pouvez faire quelques petites choses:

  1. Déplacer la définition dans un fichier .cpp et ne garder que la déclaration dans l'en-tête.
  2. Utilisez un espace de noms anonyme autour de la fonction dans votre fichier d'en-tête (mais réalisez que c'est un hack - vous aurez toujours plusieurs définitions, mais pas de collision de noms).
  3. Marquez-le comme en ligne (bien que cela ne fonctionne pas toujours - seulement si le compilateur choisit de l'aligner). C'est aussi un hack pour la même raison que ci-dessus.
5

(En supposant le code affiché est un en-tête, inclus à partir de plusieurs fichiers .cpp)

gardes en-tête ne vous protègent pas de lien à temps multiples définitions. Peu importe que vous ayez veillé à ce que l'en-tête n'apparaisse qu'une seule fois par unité de traduction, si vous avez plus d'une unité de traduction, les définitions sont multiples.

Ecrivez les définitions dans les fichiers source, et seulement les déclarations dans les en-têtes.

Les seules exceptions sont les fonctions inline, les fonctions définies dans une définition class (bien que cela ne soit pas recommandé!) Et les modèles de fonction.

+0

et les fonctions statiques, et les fonctions dans les espaces de noms anonymes :) –

+0

@Armen: Eh bien, oui, par hasard qu'ils ont un lien interne. Je pense que je continuerai à ignorer ceux-là. :) –

+0

En effet, je n'ai jamais dit que vous ne devriez pas :) –

0

100% Certains de vos gaurds d'incision sont corrects, mais obtenez toujours une erreur de redéfinition?

Pour Visual Studio: je vraiment frusterated parce que je faisais mes comprennent gaurds correctement, pour découvrir le problème était visual studio. Si vous avez ajouté le fichier à votre projet, le compilateur ajoutera le fichier deux fois même si vous avez inclure des fichiers gaurds autour de votre fichier d'implémentation et de votre fichier d'en-tête. Si vous n'utilisez pas Visual Studio exclusivement, et dites ... utilisez code :: blocks parfois, vous pourriez ne vouloir #include le fichier que lorsque vous détectez l'absence de l'environnement Visual Studio.

DebugUtil.h : 
---------------------- 
#ifndef _WIN32 
#include "DebugUtil.c" 
#endif 
---------------------- 

Si vous êtes d'accord avec y compris stdio.h, vous pouvez être un peu moins hackish à ce sujet:

DebugUtil.h : 
---------------------- 
#include <stdio.h> 
#ifdef _MSC_VER 
#include "DebugUtil.c" 
#endif 
---------------------- 

Référence: macros pré-définies, Visual Studio: https://msdn.microsoft.com/en-us/library/b0084kay.aspx

Questions connexes