como evitar el error de linker : Duplicated symbol for Architecture x86?

Iniciado por digimikeh, 28 Abril 2019, 00:19 AM

0 Miembros y 1 Visitante están viendo este tema.

digimikeh


Hola!

Tengo 4 archivos:

udbmanagement.hpp
uloginwindow.h
main.cpp
uloginwindow.cpp


main.cpp está incluyendo a "udbmanagement.hpp"
loginwindow.cpp también incluye esta misma cabecera "udbmanagement.hpp"

Sin embargo, al compilar, me envía ese error del linker, símbolos duplicados, los símbolos duplicados son 4 funciones que están dentro del archivo .hpp

El problema es que utilizo esas funciones tanto en main, como en uloginwindow.cpp

que debería hacer en este caso?..

(he probado con #pragma once pero sigo teniendo el mismo error.)

en el archivo .hpp tengo 2 structs cada una tiene algunas funciones, y esta todo definido dentro del mismo .hpp .. quizá sea mejor idea separarlos en .h y .cpp ...

Alguna idea?..
Saludos y gracias...
Dungeons & dragons;
dragons.Attack();


digimikeh

Dungeons & dragons;
dragons.Attack();

RayR

Fíjate en el archivo .pro de tu proyecto, a ver si en la sección HEADERS no tienes repetido el archivo.

digimikeh

Lo revisare, gracias.

Como dato extra, si yo retiro #include "udbmanagement.hpp" en uno de los dos archivos (solo en uno), el error desaparece... es como que no pueden estar usándose por ambos al mismo tiempo, evidentemente que debo tener símbolos duplicados si los esta invocando dos veces..

Probare lo que dices con el archivo de proyecto..
Lo otro que hare será separar el archivo .hpp en dos, .h y .cpp, me da la espina de que es mejor practica incluir las cabeceras y no las fuentes..

Comentare como me fue..
gracias!
Dungeons & dragons;
dragons.Attack();

srWhiteSkull

#5
Nunca he tenido un mac  :-\

Podrías solucionarlo cambiando el orden de compilado si ese IDE te permitiera hacerlo, algo que desconozco y si no compilarlo por línea de comando en el orden inverso.

https://www.appletonaudio.com/blog/2013/linking-c-static-libraries-with-duplicate-symbols/

Luego otra alternativa usar la opcion --whole-archive en el parámetro de la parte del enlace a las librerías, que desconozco como se haría desde ese IDE pero que podrías poner como se muestra en el enlace de abajo desde la línea de comando.

https://stackoverflow.com/questions/9093891/gcc-detect-duplicate-symbols-functions-in-static-libraries

Y ésto otro que no puedo probar :
--no-define-common
This option inhibits the assignment of addresses to common symbols. The script command "INHIBIT_COMMON_ALLOCATION" has the same effect.
The --no-define-common option allows decoupling the decision to assign addresses to Common symbols from the choice of the output file type; otherwise a non-Relocatable output type forces assigning addresses to Common symbols. Using --no-define-common allows Common symbols that are referenced from a shared library to be assigned addresses only in the main program. This eliminates the unused duplicate space in the shared library, and also prevents any possible confusion over resolving to the wrong duplicate when there are many dynamic modules with specialized search paths for runtime symbol resolution.

O

--traditional-format
For some targets, the output of ld is different in some ways from the output of some existing linker. This switch requests ld to use the traditional format instead.
For example, on SunOS, ld combines duplicate entries in the symbol string table. This can reduce the size of an output file with full debugging information by over 30 percent. Unfortunately, the SunOS "dbx" program can not read the resulting program ("gdb" has no trouble). The --traditional-format switch tells ld to not combine duplicate entries.

https://linux.die.net/man/1/ld



digimikeh

Que bien, no sabia que había más opciones, afortunadamente no envíoñ tengo tantos archivos como para que la compilacion manual sea un dolor de cabeza, probare también con lo que has mencionado, muchas gracias
Dungeons & dragons;
dragons.Attack();

RayR

Se me pasó preguntarte si habías probado la forma más obvia: los clásicos include guards. Pones en tu .h:

#ifndef NOMBRE_H
#define NOMBRE_H

//Contenido de tu archivo...

#endif


Esta es la forma estándar. Todas las demás son dependientes del compilador (aunque #pragma once es soportada por prácticamente todos). Esto no debería fallarte. Si siguiera sin funcionar, significaría  que tu IDE está haciendo algo muy, muy mal.

digimikeh

#pragma once me funciona en Visual Studio, pero no me anda en QT Creator Mac (en la versión de Windows no he probado), ..

agregare a la lista los include guards.. no los conocía..
probare mañana en mi oficina  :)
Dungeons & dragons;
dragons.Attack();

CalgaryCorpus

Apostaria mas por el flag hacia el compilador que el #ifndef o el #pragma.
Usualmente las directivas al preprocesador tendran efecto si al compilar 1 programa, este #incluye mas de 1 vez el mismo codigo en esa operacion.
Pero si estas compilando 2 archivos .cpp, como indicas, y ambos hacen #include, el compilador no tiene manera de saber lo que #incluiste antes y no va a tener efecto el #ifndef o #pragma.

Si el archivo #incluido tiene funciones, como parece ser el caso, a ninguna de las 2 compilaciones le molestara', pero el linker descubrira' esto y reclamara' de la duplicacion de codigo, como lo esta haciendo ahora.

Sugiero eliminar la presencia de funciones en los archivos #incluidos. quedandose solamente con la definicion de tipos y la especificacion de prototipos de funciones, haciendo su implementacion en un archivo .cpp aparte.
Aqui mi perfil en LinkedIn, invitame un cafe aqui