PDA

View Full Version : [C] gcc - multiple definition of...


nico88desmo
29-09-2007, 14:20
Buongiorno!

Durante la compilazione di un programmino in C, il compilatore gcc mi dà in output questo errorino:

gcc -o main_mate main_mate.c lib.a
lib.a(lib_mate.o):(.data+0x0): multiple definition of `LIB_SIMBOLI'
/tmp/ccwhL9qR.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status


I file sono 3:
- main_mate.c = programmino dove viene lanciato il programma;
- lib_mate.h = libreria che contiene strutture e dichirazione funzioni;
- lib_mate.c = sorgente dove viene scritto il corpo delle funzioni della libreria:

Per la compilazione faccio questi passaggi:
1) gcc -c -o lib_mate.o lib_mate.c
2) ar r lib.a lib_mate.o
3) gcc -c -o main_mate main_mate.c
4) gcc -o main_mate main_mate.c lib.a

L'errore significa che ci sono più definizioni di `LIB_SIMBOLI` ma quest'ultimo è stato definito solamente nel sorgente "lib_mate.h".
Cosa potrebbe essere allora???

Torav
29-09-2007, 14:56
se non hai usato #ifndef e #define forse rischi di includere più volte lo stesso .h e quindi in effetti il compilatore vede la roba definita 2 volte! non so eh...senza vedere i sorgenti non so essere più preciso

nico88desmo
29-09-2007, 15:00
se non hai usato #ifndef e #define forse rischi di includere più volte lo stesso .h e quindi in effetti il compilatore vede la roba definita 2 volte! non so eh...senza vedere i sorgenti non so essere più preciso

Io ho definito così la libreria all'interno del file `lib_mate.h`;

#ifndef __lib_mate_h_
#define __lib_mate_h_


e ora ho provato a togliere i 2 underscore, quindi risulta così:

#ifndef lib_mate_h
#define lib_mate_h


però niente..mi dà sempre lo stesso errore..

Torav
29-09-2007, 15:26
scusami ma non capisco il terzo passaggio..in teoria tu compili la tua libreria e va bene, poi dovresti semplicemente compilare il programma principale, quello che ha il main() per intenderci, e poi fai una cosa tipo:

gcc -o main_mate main_mate.c -llib -L.

con -l gli dici dove cercare la libreria (che in questo caso è lib.a, bisogna passare dopo il -l semplicemente il nome del .a senza l'estensione)
con -L invece gli dici dove cercare l'header (in questo caso . perchè è nella dir corrente)

se invece vuoi evitarti il fatto di fare una libreria basta fare

gcc -o main_mate main_mate.c lib_mate.c

nico88desmo
29-09-2007, 15:29
L'errore è provocato dalle seguente riga di codice

char *(LIB_SIMBOLI[]) = {"+","-","*","/","sin","cos","tan","asin","acos","atan","log","^","%"};


Vorrei definire un vettore all'interno del file header?
Come si fa?

andbin
29-09-2007, 15:31
L'errore significa che ci sono più definizioni di `LIB_SIMBOLI` ma quest'ultimo è stato definito solamente nel sorgente "lib_mate.h".Nei file di header NON si devono fare definizioni di variabili o funzioni.

nico88desmo
29-09-2007, 15:34
Nei file di header NON si devono fare definizioni di variabili o funzioni.

Ma nemmeno le costanti?

nico88desmo
29-09-2007, 15:38
scusami ma non capisco il terzo passaggio..in teoria tu compili la tua libreria e va bene, poi dovresti semplicemente compilare il programma principale, quello che ha il main() per intenderci, e poi fai una cosa tipo:

gcc -o main_mate main_mate.c -llib -L.

con -l gli dici dove cercare la libreria (che in questo caso è lib.a, bisogna passare dopo il -l semplicemente il nome del .a senza l'estensione)
con -L invece gli dici dove cercare l'header (in questo caso . perchè è nella dir corrente)

se invece vuoi evitarti il fatto di fare una libreria basta fare

gcc -o main_mate main_mate.c lib_mate.c

Si, infatti il terzo passaggio ho notato che non serve a nulla :)
Per il gcc.... -l è per le librerie statiche o non fà differenza tra statiche e dinamiche?

andbin
29-09-2007, 15:42
Ma nemmeno le costanti?Quella LIB_SIMBOLI non è una costante ... è una variabile (e tra l'altro le parentesi tonde non servono).

Il problema è semplice: se in un file di header si fanno definizioni che allocano memoria come appunto definire una variabile o una funzione, allora tali definizioni fanno poi parte del modulo oggetto compilato. Che succede se al linker arrivano più moduli oggetto che contengono simboli con lo stesso nome? ;)

nico88desmo
29-09-2007, 15:48
Quella LIB_SIMBOLI non è una costante ... è una variabile (e tra l'altro le parentesi tonde non servono).

Il problema è semplice: se in un file di header si fanno definizioni che allocano memoria come appunto definire una variabile o una funzione, allora tali definizioni fanno poi parte del modulo oggetto compilato. Che succede se al linker arrivano più moduli oggetto che contengono simboli con lo stesso nome? ;)

Succede Caos :D
Se io volessi dichiarare quel vettore e renderlo visibile a più sorgenti, potrei fare così?
Prima lo dichiaro in un sorgente e successivamente negli altri sorgenti .c, farlo riconoscere mediante la parole chiave "extern"..

andbin
29-09-2007, 16:22
Prima lo dichiaro in un sorgente e successivamente negli altri sorgenti .c, farlo riconoscere mediante la parole chiave "extern"..Appunto ... si fa la definizione in un sorgente .c e poi negli altri sorgenti (o meglio magari in un header incluso dai sorgenti) si fa una allusione alla variabile/funzione tramite extern (per i prototipi di funzione extern è superfluo).

nico88desmo
29-09-2007, 16:45
Appunto ... si fa la definizione in un sorgente .c e poi negli altri sorgenti (o meglio magari in un header incluso dai sorgenti) si fa una allusione alla variabile/funzione tramite extern (per i prototipi di funzione extern è superfluo).

Perfetto. Fatto così e funziona tutto! :D

recoil
29-09-2007, 17:32
in alcuni casi (non nel tuo) un errore del genere può essere causato da qualche inesattezza nel Makefile
io ad esempio una volta ho perso 10 minuti prima di capire che mettevo lo stesso .o due volte nel Makefile, con una sfilza impressionante di errori "multiple definition of..." :asd:

Andrea16v
29-09-2007, 23:36
Mi accodo al thread per chiedere: anche nel caso di una variabile intera condivisa tra piu' files, non è buona norma dichiararla nel file.h incluso da tutti ? Mi servirebbe sia visibile da tutti i files che compongono il programma, senza passarla come parametro da un metodo all'altro...

71104
30-09-2007, 08:16
edit scusate :D

nico88desmo
30-09-2007, 10:38
Mi accodo al thread per chiedere: anche nel caso di una variabile intera condivisa tra piu' files, non è buona norma dichiararla nel file.h incluso da tutti ? Mi servirebbe sia visibile da tutti i files che compongono il programma, senza passarla come parametro da un metodo all'altro...

Io la metterei nel file .h


#define VARIABILE_INTERA 1000


Così facendo però non hai una variabile...è una define che è diverso.
Se la variabile che ti serve è costante allora farei così, altrimenti no.
Il mio problema era che dovevo dichiarare un vettore di stringhe...per questo ho dovuto dichiararlo nel file .c

recoil
01-10-2007, 13:15
la dichiari in uno e poi la metti come extern negli altri
non è bello ma in alcuni casi è necessario

ilsensine
01-10-2007, 14:22
In alternativa si può usare (nei .h)

__attribute__((section(".gnu.linkonce"))) int var;

ottenendo un codice di assoluta nonportabilità e di dubbia leggibilità.

E' meglio implementarla in un file sorgente e dichiararla come extern negli header.