2011-04-05 9 views
39

In quale situazione è possibile che GCC per non emetta un messaggio di errore "collegamento di riferimento non definito" quando si tenta di richiamare le funzioni configurate?GCC non può lamentarsi di riferimenti non definiti?

Per esempio, una situazione in cui questo codice C viene compilato e collegato da GCC:

void function() 
{ 
    made_up_function_name(); 
    return; 
} 

... anche se non è presente made_up_function_nameovunque nel codice (non intestazioni, i file di origine, dichiarazioni, né alcuna libreria di terze parti).

Questo tipo di codice può essere accettato e compilato da GCC in determinate condizioni, senza toccare il codice effettivo? Se sì, quale?

Grazie.

MODIFICA: nessuna dichiarazione precedente o menzione a made_up_function_name è presente altrove. Significa che uno grep -R dell'intero filesystem sarà solo e mostrerà quell'esatta riga di codice.

+0

Può (purché si compili C, non C++). Cosa stai cercando di realizzare? –

+0

Non sto cercando di realizzare nulla, sta già accadendo e mi piacerebbe sapere perché è possibile. Made_up_function_name è effettivamente presente nel binario linkato finale se uso "-g" e modifica il file con un editor di testo. – STenyaK

+1

Per quanto riguarda il motivo, vedere: http://stackoverflow.com/questions/4914589/c-prototype-functions/4914683, http://stackoverflow.com/questions/4800102/not-including-stdlib-h-does-not -produce-any-compiler-error/4800138 # 4800138, e probabilmente un po 'di più. –

risposta

68

Sì, è possibile evitare di segnalare riferimenti non definiti utilizzando l'opzione di collegamento --unresolved-symbols.

g++ mm.cpp -Wl,--unresolved-symbols=ignore-in-object-files 

Da man ld

--unresolved-simboli = Metodo

stabilire come gestire simboli non risolti. Ci sono quattro valori possibili per il metodo:

 ignore-all 
      Do not report any unresolved symbols. 

     report-all 
      Report all unresolved symbols. This is the default. 

     ignore-in-object-files 
      Report unresolved symbols that are contained in shared 
      libraries, but ignore them if they come from regular object 
      files. 

     ignore-in-shared-libs 
      Report unresolved symbols that come from regular object 
      files, but ignore them if they come from shared libraries. This 
      can be useful when creating a dynamic binary and it is known 
      that all the shared libraries that it should be referencing 
      are included on the linker's command line. 

Il comportamento per le librerie condivise per conto proprio può anche essere controllato da l 'opzione - [no-] allow-shlib-indefinito.

Normalmente il linker genera un messaggio di errore per ogni simbolo non risolto segnalato da ma l'opzione --warn-non risolto - i simboli possono modificarlo in un avviso.

3

Se si dichiara il prototipo della funzione prima di utilizzarlo, viene compilato. In ogni caso l'errore durante il collegamento rimarrà.

void made_up_function_name(); 
void function() 
{ 
    made_up_function_name(); 
    return; 
} 
+0

Domande modificate per riflettere questo: non c'è assolutamente nessun altro riferimento alla funzione composta, oltre alla linea di chiamata mostrata nell'esempio. – STenyaK

1

Se function() non è mai chiamato, potrebbe non essere incluso nel file eseguibile, e la funzione chiamata da esso non viene cercato per entrambi.

+0

quindi potrebbe compilare anche senza dichiarare il prototipo e quindi essere collegato anche tu? Penso che almeno il prototipo dovrebbe essere dichiarato, altrimenti genererebbe un errore di analisi, giusto? – Heisenbug

+0

@ 0verbose - Dipende dallo standard C utilizzato. Originariamente, i prototipi non erano necessari. E più tardi solo se avevi tipi di parametri diversi da int. –

0

E poi c'è questa cattiveria con il flag -D passato a GCC.

$cat undefined.c 
void function() 
{ 
    made_up_function_name(); 
    return; 
} 


int main(){ 
} 

$gcc undefined.c -Dmade_up_function_name=atexit 
$ 

Provate a immaginare che cerca la definizione di made_up_function_name- appare da nessuna parte "fa le cose" nel codice ancora. Non riesco a pensare ad una buona ragione per fare questa cosa esatta nel codice.

Il flag -D è un potente strumento per modificare il codice in fase di compilazione.

+0

Il flag '-D' cambia il codice al momento * compile *. Poi ci sono cose come '-Wl, - wrap' che lo fa al momento del collegamento. –

+0

E se uno combina '-D' con la fusione di token pre-processore, il testo' made_up_function_name' non deve apparire come tale in alcun makefile o script di costruzione. –

2

TL; DR E può non si lamentano, ma non voglio questo. Il tuo codice andrà in crash se imponi al linker di ignorare il problema. Sarebbe controproducente.

Il tuo codice si basa sull'antica C (pre-C99) che consente di dichiarare implicitamente le funzioni nel punto di utilizzo. Il tuo codice è semanticamente equivalenti al seguente codice:

void function() 
{ 
    int made_up_function_name(...); // The implicit declaration 

    made_up_function_name(); // Call the function 
    return; 
} 

Il linker lamenta giustamente che il file oggetto che contiene il compilato function() fa riferimento a un simbolo che non è stato trovato altrove. Devi risolvere il problema con fornendo l'implementazione per made_up_function_name()o rimuovendo la chiamata senza senso. Questo è tutto ciò che c'è da fare. Nessun linker coinvolgente.

0

L'algoritmo "standard" in base al quale operano i collegamenti POSIX lascia aperta la possibilità che il codice venga compilato e collegato senza errori. Vedi qui per maggiori dettagli: https://stackoverflow.com/a/11894098/187690

al fine di sfruttare questa possibilità il file oggetto che contiene il function (chiamiamolo f.o) deve essere posto in una libreria. Quella libreria dovrebbe essere menzionata nella riga di comando del compilatore (e/o del linker), ma in quel momento nessun altro file oggetto (menzionato prima nella riga di comando) avrebbe dovuto effettuare chiamate a function o qualsiasi altra funzione presente in f.o. In tali circostanze il linker non vedrà alcun motivo per recuperare f.o dalla libreria. Linker ignorerà completamente f.o, ignorerà completamente function e, pertanto, rimarrà completamente ignaro della chiamata a made_up_function_name. Il codice verrà compilato anche se made_up_function_name non è definito da nessuna parte.

1

Quando si crea con il flag di collegamento -r o --relocatable, non verrà generato alcun messaggio di errore di collegamento "riferimento non definito".

Questo perché -r collegherà diversi oggetti in un nuovo file oggetto da collegare in una fase successiva.

Problemi correlati