PDA

View Full Version : [C] undefined reference


sharkkk
13-02-2014, 14:49
salve a tutti,

allora, ho un progetto con due file .h e un file .c (con il main):

- prototipi delle funzioni nel file primo.h
- implementazioni delle funzioni del file primo.h nel file secondo.h

- inclusione dei due file .h nel file .c dove c'e il main ecc

quando compilo non ci sono errori, ma quando interviene il linker (giusto?) mi da [LINKER ERROR]undefined reference a tutte le funzioni che io ho dichiarato e implementato.

dove sto sbagliando:(

Daniels118
13-02-2014, 15:30
I prototipi delle funzioni vanno bene nel file .h, ma l'implementazione va nei file .c. Comincia a correggere, se hai ancora problemi scrivi i messaggi di errore esatti.

sharkkk
13-02-2014, 15:39
I prototipi delle funzioni vanno bene nel file .h, ma l'implementazione va nei file .c. Comincia a correggere, se hai ancora problemi scrivi i messaggi di errore esatti.

a questo punto pero devo creare un makefile è giusto?

oppure posso includere il file con le implementazioni delle funzioni (secondo.c) direttamente nel main.c con #include "secondo.c"

perchè non mi è mai capitato di usare due file .c nello stesso progetto :(

Daniels118
13-02-2014, 15:43
Si, puoi mettere tutto nel main, comunque non è necessario creare il makefile, il compilatore dovrebbe poter compilare più file in un colpo solo, consulta l'help del tuo compilatore per vedere qual'è la sintassi.

sharkkk
13-02-2014, 15:54
daniels ho provato ad includere il file con #include "secondo.c" (si trova nella stessa cartella del main.c) ma da ancora gli stessi errori di undefined reference.

il compilatore è gcc però per un particolare progetto di sistemi operativi.

a questo punto l'unica alternativa è studiarmi come si crea un makefile giusto? (beh alla fine avrei dovuto impararlo :muro: )

p.s.
considerando che il main.c si appoggia su funzioni che stanno nel file secondo.c i cui prototipi stanno in primo.h, qual'è diciamo l'albero delle dipendenze (sto guardando un po di guide e questa cosa ancora mi è sfuggita)
chi ha più priorità nella compilazione?

Daniels118
13-02-2014, 16:10
I file .c non vanno inclusi, ma compilati, e i risultati della compilazione (.o) vanno linkati insieme nell'eseguibile.
Non è che non si possano includere i file .c, ma tra regole e convenzioni si rischia di fare un casino, cerchiamo di parlare tutti la stessa lingua :)

Daniels118
13-02-2014, 16:16
Ho visto ora che hai aggiornato la risposta...
non è una questione di priorità, i file .c possono essere compilati in modo del tutto indipendente tra loro. Se una funzione F definita nel file A viene richiamata nel file B, è sufficiente che B includa l'header dove c'è il prototipo di F. L'header non deve contenere né variabili né istruzioni, ma solo direttive e definizioni, così può essere incluso in più file .c senza che in fase di link si ci ritrovi con codice o dati duplicati.

sharkkk
13-02-2014, 19:48
non ci sto capendo piu nulla, questa parte mi sembra difficile anche se immagino che in realtà sia facilissimo.

ho capito che:
compilo A.c facendolo diventare A.o
compilo B.c facendolo diventare B.o

ho guardato delle guide sui makefile ma ciò che trovo sono tutti argomenti sulle dipendenze, ma come faccio a linkare A.o a B.o?:cry:

p.s. esiste l'estensione .e?

lorenzo001
13-02-2014, 20:35
Non includere i file.c ...

Scrivi

gcc -o eseguibile main.c file1.c file2.c

sharkkk
14-02-2014, 11:44
Non includere i file.c ...

Scrivi

gcc -o eseguibile main.c file1.c file2.c


per compilare di solito usavo scrivere

gcc -c -o eseguibile file.c (non so pero cosa significhi il comando -c)

il tuo comando mi continua a dare errori di undefined reference.:cry:

provo a spiegare meglio il progetto come è costruito:

main.c - inclusioni di const.h, funzioni.h
const.h - costanti (nessuna inclusione)
funzioni.h - definizioni delle strutture e dei prototipi delle funzioni (nessuna inclusione)
funzioni.c - implementazione delle funzioni con le strutture e le costanti (nessuna inclusione)

il problema è che sto provando in mille modi ma non capisco come compilare il tutto senza darmi errori di [LINKER ERROR] undefined reference funzione pippo, [LINKER ERROR] undefined reference funzione pluto,..... .

come devo procedere passo per passo per far si che compili :muro: :cry: :cry: :muro: :muro: :muro: ?

clockover
14-02-2014, 12:15
Esempio molto idiota

File --> fact.c

int fattoriale(int value){
if(value <= 0)return 1;
if(value == 2)return 2;
int tmp = value--;
while(value > 1)tmp *= value--;
return tmp;
}

File --> main.c

#include "head.h"

int main(int argn, char ** argp){
int value = 8;
printf("Il fattoriale di %d è %d\n", value, fattoriale(value));
return 0;
}

File --> head.h

#include <stdio.h>
#include <stdlib.h>

int fattoriale(int);


Compilazione:
1) gcc -o eseguibile main.c fact.c

oppure

2) gcc -c main.c fact.c / oppure gcc -c *.c
gcc -o eseguibile main.o fact.o / oppure gcc -o eseguibile *.o

Quando esegui gcc -c crei soltanto i files oggetto (estensione .o) e non esegui il linker. Se ometti -c crei file oggetto e richiami anche il linker.

Dai uno sguardo qui --> http://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html

Trucco numero 1 per capirci qualcosa: fai prove stupide e semplici come quella che ti ho fatto vedere io qui sopra.
Quando tu mi scrivi

"per compilare di solito usavo scrivere

gcc -c -o eseguibile file.c (non so pero cosa significhi il comando -c)"

vuol dire che stai digitando comandi a memoria e senza capire... fai prove stupide e semplici e piano piano farai bene progetti più grandi... :)

Daniels118
14-02-2014, 12:30
Nel file funzioni funzioni.c devi includere funzioni.h. Per spiegarti il perchè ti faccio un semplice esempio:
void A() {
B();
}

void B() {
...
}
In questo caso viene generato un errore di compilazione perché il compilatore vede una chiamata a B, ma questa non è stata ancora definita.

Comunque non è quello il problema, perché l'errore non viene generato nella fase di compilazione, ma in quella di link, e ciò significa che la funzione "undefined" non si trova in nessuno dei file che stai linkando insieme.

Ti ricordo inoltre che il c è case sensitive, "pluto" è diverso da "Pluto".

sharkkk
14-02-2014, 12:35
Compilazione:
1) gcc -o eseguibile main.c fact.c

oppure

2) gcc -c main.c fact.c / oppure gcc -c *.c
gcc -o eseguibile main.o fact.o / oppure gcc -o eseguibile *.o


grazie mille per la risposta clock.

penso di aver capito la tua spiegazione, ma quando lancio il comando

gcc -c main.c funzioni.c

il programma mi da errore, perche non mi riconosce le strutture (in funzioni.h) e le costanti (const.h) nel file funzioni.c

:cry:

sharkkk
14-02-2014, 12:41
Nel file funzioni funzioni.c devi includere funzioni.h. Per spiegarti il perchè ti faccio un semplice esempio:
void A() {
B();
}

void B() {
...
}
In questo caso viene generato un errore di compilazione perché il compilatore vede una chiamata a B, ma questa non è stata ancora definita.

Comunque non è quello il problema, perché l'errore non viene generato nella fase di compilazione, ma in quella di link, e ciò significa che la funzione "undefined" non si trova in nessuno dei file che stai linkando insieme.

Ti ricordo inoltre che il c è case sensitive, "pluto" è diverso da "Pluto".

ho incluso funzioni.h e anche const.h e ora funziona bene, mi ha creato 2 file oggetto.

ora come devo fare per linkarli?

Daniels118
14-02-2014, 12:41
EDIT:
Possiamo avere l'onore di vedere il tuo programma top-secreet? :p
Come ha detto clockover:
gcc -o eseguibile.exe main.o funzioni.o

sharkkk
14-02-2014, 12:43
Possiamo avere l'onore di vedere il tuo programma top-secreet? :p

sarebbe lunghissimo, perche in realtà io l'ho semplificato moltissimo, posso contattarti in privato per mostrartelo?

sharkkk
14-02-2014, 15:03
risolto!

bisogna usare il comando LD

clockover
14-02-2014, 16:20
risolto!

bisogna usare il comando LD

In realtà gcc utilizza proprio ld

Inviato da una supercazzola ed un Nexus 5 scappellato a sinistra.. con senso unico

Daniels118
14-02-2014, 16:49
Misteri del G-C-C... :D

lorenzo001
14-02-2014, 17:35
risolto!

bisogna usare il comando LD

Ti avevo detto di usare

gcc -o eseguibile file1.c file2.c

che eseguiva anche il linker ma non l'hai fatto.

Hai voluto generare solo i file oggetto con

gcc -c ...

per poi scoprire, entusiasta, che non eseguiva il linker che potevi eseguire a parte ...

Ma seguire il primo consiglio che ti avevo dato, no ?

sharkkk
15-02-2014, 09:50
Ti avevo detto di usare

gcc -o eseguibile file1.c file2.c

che eseguiva anche il linker ma non l'hai fatto.

Hai voluto generare solo i file oggetto con

gcc -c ...

per poi scoprire, entusiasta, che non eseguiva il linker che potevi eseguire a parte ...

Ma seguire il primo consiglio che ti avevo dato, no ?

credimi l'ho fatto, ma ho commesso un gravissimo errore omettendo il fatto che dovevo linkare quei sorgenti anche a più librerie di sistema, e per farlo dovevo usare il comando LD .

i vostri aiuti mi sono stati di enorme aiuto perche senza di voi non avrei capito bene come funziona la compilazione e il linking con gcc