2011-06-24 16 views
33

DebugUtil.hUno o más símbolos se multiplican definidos encontraron

#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 

Cuando trato de ejecutar este me sale este error:

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

Pero, ¿por qué sucede esto? Tengo #ifndef #define y #endif en el encabezado por lo que no deberían aparecer varias definiciones

+0

posible duplicado de [Error de enlace con funciones realmente simples C++ en archivo .h] (http://stackoverflow.com/questions/6424911/link-error-with-really-simple-functions-c-on-h-file) –

+0

@ Armen: Es como Hame que las respuestas sobre esta pregunta son mucho mejores :( –

Respuesta

54

Ponga la definición (cuerpo) en un archivo cpp y deje solo la declaración en un archivo h. Incluya guardias que operen solo dentro de una unidad de traducción (también conocido como archivo fuente), no en todo su programa.

La regla de una definición de la norma C++ establece que debe aparecer exactamente una definición de cada función no en línea que se utiliza en el programa. Entonces, otra alternativa sería hacer su función en línea.

+2

Tengo el mismo problema. Tengo algunos valores constantes en un espacio de nombres en mi archivo de encabezado. Esta es una biblioteca de matemáticas, así que les di instrucciones, pero ¿qué pasa con los valores constantes? –

+0

@ CahitBurakKüçüksütcü: las variables constantes tienen un enlace interno; no debería haber ningún problema al tenerlos en el archivo de encabezado –

+0

OMFG DAME TU F-ING PAYPALL ILL DONA TAN MUCHO DINERO QUE MFKR – Acidic

10

Haga la función en línea o declare la función en un archivo de cabecera y defínalo en un archivo cpp.

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

    return 0; 
} 

EDIT:

Como comentario por Tomalak Geret'kal sugiere, es mejor utilizar mis últimas sugerencias que mi ex y mover la declaración de la función en un archivo CPP.

+2

'inline'ing es algo en lo que debes pensar cuando quieras alinear la función, no es algo que uso para hackear un error del compilador porque no entiendes lo que está pasando. –

+0

@Tomalak Geret'kal: Estoy de acuerdo en que lo es y normalmente no lo hago, pero puede ser conveniente si se trata de una función pequeña que va a utilizar en todo su programa. – GWW

+0

Y eso está bien. Sin embargo, tales criterios faltaban en su respuesta. –

0

Mueva la definición a un archivo .cpp.

0

Declare sus funciones en archivos C++. Como definió su función en el archivo de encabezado y ese archivo de encabezado se incluye desde varios archivos de origen, se define para cada archivo fuente que lo incluye. Es por eso que se informa que se define en varios lugares.

Como alternativa, puede hacer que esté en línea para que el código se inserte donde sea que se use en lugar de definirse como una función separada cada vez.

0

Parece que está incluyendo DebugUtil.h en más de una unidad de traducción, y luego une esos objetos. Sin embargo, DebugUtil.h proporciona una definición para la función DebugMessage, por lo que esa definición existe en todas las unidades de traducción que incorporaron el encabezado. Como resultado, cuando vincula los objetos, el vinculador se queja con razón de que el símbolo está definido de forma múltiple.

Cambie DebugUtil.h para que declare DebugMessage a través de un prototipo, pero no proporcione una definición, y coloque la definición de DebugMessage en un archivo .c que compilará y vinculará con sus otros objetos.

0

Eso solo evita inclusiones múltiples en el mismo archivo fuente; múltiples archivos fuente #include ing aún generará múltiples definiciones de DebugMessage(). En general, no debe colocar funciones en archivos de encabezado o hacerlas static (y generalmente inline, ya que de lo contrario, generalmente no tiene sentido tener múltiples definiciones static de la misma función).

3

Esta función está incluida en cada unidad de traducción y, como resultado, obtiene múltiples definiciones de la misma: cada archivo .obj contiene su propia copia. Cuando llega el momento de vincularlos, el vinculador muestra correctamente el error anterior.

Usted puede hacer algunas cosas:

  1. Mover la definición de un archivo .cpp y mantener sólo la declaración en la cabecera.
  2. Use un espacio de nombre anónimo alrededor de la función en su archivo de encabezado (pero tenga en cuenta que es un truco, todavía tendrá múltiples definiciones, simplemente no habrá colisión de nombres).
  3. Marcarlo como en línea (aunque puede que no siempre funcione, solo si el compilador realmente elige alinearlo). Eso también es un truco por la misma razón que la anterior.
5

(Suponiendo que el código publicado es un encabezado, incluido desde múltiples archivos .cpp)

guardias de cabecera no lo protegen de tiempo de enlace múltiples definiciones. Independientemente de que se haya asegurado de que el encabezado solo aparezca una vez por cada Unidad de traducción, si tiene más de una Unidad de traducción, eso significará múltiples definiciones.

Escribir definiciones en archivos fuente, y solo declaraciones en encabezados.

Las únicas excepciones son inline funciones, funciones definidas dentro de una definición class (¡aunque esto no se recomienda!) Y plantillas de funciones.

+0

y funciones estáticas, y funciones en espacios de nombres anónimos :) –

+0

@Armen: Bueno, sí, por casualidad que tienen enlaces internos. Creo que continuaré ignorando esos. :) –

+0

De hecho, nunca dije que no deberías :) –

0

100% ¿Estás seguro de que tus puertas incuras son correctas, pero sigues recibiendo un error de redefinición?

Para Visual Studio: yo estaba realmente frusterated porque yo estaba haciendo mi incluyen gaurds correctamente, sólo para descubrir que el problema era el estudio visual. Si ha agregado el archivo a su proyecto, el compilador agregará el archivo dos veces aunque tenga incluyendo gaurds alrededor de su archivo de implementación y encabezado.

Si no usa Visual Studio exclusivamente, y digamos ... use code :: blocks a veces, es posible que desee #incluir el archivo cuando detecta la ausencia del entorno de Visual Studio.

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

Si estás bien con la inclusión de stdio.h, puede ser un poco menos hacker al respecto:

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

Referencia: predefinidas macros, Visual Studio: https://msdn.microsoft.com/en-us/library/b0084kay.aspx

Cuestiones relacionadas