2013-03-05 15 views
7

Sto compilando il mio codice sorgente su 2 macchine diverse che utilizzano versioni diverse di gcc.compilazione del codice sorgente su 2 diverse versioni di gcc

cflags C89

-Wall -Wextra -Wunreachable-code -g -m32 -D_DEBUG -O0 -D_LARGEFILE64_SOURCE -D_REETRANT -D_THREAD_SAFE 

Uno è RedHat-4

gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46) 
Linux 203_test_server 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:48 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux 

e uno è Fedora 18

gcc (GCC) 4.7.2 20121109 (Red Hat 4.7.2-8) 
Linux localhost.localdomain 3.8.1-201.fc18.x86_64 #1 SMP Thu Feb 28 19:23:08 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux 

miei fedora 18 compila senza errori. Tuttavia, sulla macchina di Redhat 4 ottengo alcuni errori.

channel.h:35: error: redefinition of typedef ‘channel_t’ 
internal.h:19: error: previous declaration of ‘channel_t’ was here 

Penso che l'errore sia solo un problema circolare. Tuttavia, con la stessa base di codice, la compilazione su 2 macchine diverse può davvero fare la differenza usando 2 diverse versioni di gcc?

Stavo pensando che l'uso di una versione più recente di un compilatore genererà più errori, poiché il compilatore più recente potrebbe essere più rigido.

Questa non è una domanda per risolvere l'errore, ma una domanda generale sui compilatori.

C'è qualche indicatore che posso impostare per evitare questo in futuro. Forse se la compilazione su questa versione di gcc lo fa, se le versioni non sono compatibili?

+1

Sì, diversi compilatori/versioni/flag potrebbero produrre risultati diversi, esp. nel codice '# ifdef'-pesante. –

+0

per quanto riguarda "qualsiasi flag che posso impostare per evitare questo in futuro", la mia risposta lo copre, o stavi pensando a qualcosa di diverso? – Mike

+0

alcune informazioni utili sarebbero carine, è più probabile che sia un'intestazione inclusa diversa su un sistema rispetto al compilatore, ma non si menziona mai dove sono channel.h o internal.h o come vengono inclusi. anche le linee circostanti intorno a dove appare channel_t sarebbero utili ... almeno per gli ifdef. Il tuo CFLAG definisce non significa assolutamente nulla senza quello. – technosaurus

risposta

4

Questo è un duplicato di: Why "Redefinition of typedef" error with GCC 4.3 but not GCC 4.6?

La risposta è che gcc è stato cambiato per modificare questo controllo.

http://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=ce3765bf44e49ef0568a1ad4a0b7f807591d6412

A volte, le avvertenze per il comportamento definiti nel linguaggio, ma considerato cattiva pratica, sono considerate troppo rigide perché certi casi d'uso utile e/o innocui sono compresi nel avvertimento. Gli sviluppatori di compilatori tentano quindi di risolvere il problema in modo opposto, ovvero riducendo la quantità di avvisi. In questo caso, la modifica ha fatto apparire l'avviso solo quando la seconda definizione ha cambiato il typedef in un tipo diverso, ma compatibile.

Altro esempio attuale è -Whadow in gcc 4.8 appena annunciato. Nella nota di rilascio, si dice che -Whadow non avviserà più se un nome di funzione è ombreggiato da un altro.

See: http://gcc.gnu.org/gcc-4.8/changes.html

Edit: come si può evitare questo: o eliminare una delle definizioni, o spostarlo in un separato include file ed eliminare entrambe le altre definizioni.

10

Dipende da quali intestazioni vengono incluse dal codice sorgente. Se si esegue il collegamento a librerie esterne, è possibile che il codice sorgente sia incompatibile con la versione di una libreria installata nel sistema precedente.

Se il codice sorgente non include alcuna intestazione di libreria esterna (eccetto la libreria C), potrebbero esserci direttive del preprocessore che devono essere modificate.

EDIT:

Dopo una ricerca Google, sembra che channel_t da un colpo di testa del kernel. Stai usando versioni del kernel molto distanti tra le due macchine. Se il codice dipende da un file di intestazione del kernel, potrebbe richiedere una versione del kernel più recente rispetto alla macchina Red Hat. Non hai specificato quale sia il codice (si tratta di un driver di dispositivo?), O quali file è incluso, quindi è difficile dire di più.

+0

Le tue risposte sono belle, quindi +1 ti darò un tag 'nice' .. –

+0

@GrijeshChauhan: grazie! – teppic

4

Confrontare i contenuti di channel.h e internal.h sui due sistemi in cui si ottengono risultati diversi. Dubito che il problema sia la versione di gcc. È più probabile che gli errori siano il risultato di modifiche di codice a quei file nel tempo, come quando un sistema ha una versione più recente di una libreria e i relativi file di intestazione rispetto agli altri.

1

Per cominciare, parliamo un po 'del problema. Penso che la causa più probabile del sistema che dà errori su un sistema rispetto all'altro è che il codice non è identico; potresti voler verificare questo tramite qualche strumento o il comando diff per cercare eventuali modifiche sottili presenti nella tua base di codice. problemi Normalmente, quando ho visto con quel tipo di errore, si hanno qualcosa di simile:

typedef struct Foo* Fooptr; 

In un file di intestazione e quindi:

typedef struct Foo 
{ 
    int bar; 
} *Fooptr; 

nel file di origine. Il che significa che puoi semplicemente rilasciare il typedef nella sorgente e dovrebbe essere OK. Solo qualcosa da cercare.

Ora, se è una questione gcc, una seconda opzione per risolvere il tuo problema, è possibile have multiple versions of gcc on the same computer e poi per specificare l'esatta versione del gcc a correre con tramite l'opzione -v. Quindi potrebbe essere una buona idea dare un 4.1.2 alla tua macchina Fedora 18.

Un'altra nota, se si utilizza l'opzione -v, ma non specificare una versione di gcc a correre, si otterrà (sull'uscita stderr) i comandi eseguiti per eseguire le fasi di compilazione. Questo potrebbe essere utile per vedere cosa sta succedendo e se ci sono grosse differenze tra ciò che accade su ciascuna macchina.


OK, ora alle vostre domande. Sì, ci sono contrassegni per la compilazione sulla "versione X" di gcc: Per i principianti c'è lo __VERSION__ Predefined Macro, questo ti restituirà un numero di versione const char *. Questo può essere molto utile, ma come la documentazione gcc afferma:

Si consiglia di non fare affidamento su suo contenuto, aventi una forma particolare, ma può essere contato su per contenere almeno il numero di release

Nonostante ciò, in genere ho visto solo 1 forma di output da questo che è qualcosa come "4.6.3" se la mia versione di gcc è 4.6.3-1ubuntu5.

Ora, se si sa (o sospetta) che alcuni del codice causerà una particolare versione di gcc per causare errori è possibile utilizzare i __GNUC__, __GNUC_MINOR__ e __GNUC_PATCHLEVEL__ macro predefinite per "proteggere" voi stessi:
Ecco un breve snip-it che mostra al più alto livello come usarlo:

#if __GNC__ == 3 
    printf(“Hello version 3.x.x\n”); 
#elif __GNC__ == 4 
    printf(“Hello version 4.x.x\n”); 
#endif 

Così il sistema di cui sopra, dove la versione è 4.6.3 che ci si vede il messaggio “Ciao versione 4.xx”. Poi si può ottenere di più avanzato e controllare le sovversioni così:

#if __GNUC__ > 3 || \ 
    (__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || \ 
     (__GNUC_MINOR__ == 2 && \ 
      __GNUC_PATCHLEVEL__ > 0)) 
    printf(“I’m a gcc greater than 3.2.0\n”); 
#endif 

o la versione più pulita di quella utilizzando la propria macro:

#define GCC_VERSION (__GNUC__ * 10000 \ 
    + __GNUC_MINOR__ * 100 \ 
    + __GNUC_PATCHLEVEL__) 
#if GCC_VERSION > 30200 
    printf(“I’m a gcc greater than 3.2.0\n”); 
#endif 

Per rispondere alla sua domanda circa se diverse versioni di gcc produrrà diversi errori, sei corretto che in ogni versione di gcc ci sia ancora qualcosa in più e qualche volta le cose cambiano, quindi vedrai le differenze tra le diverse versioni del compilatore. La soluzione migliore è controllare le note di rilascio per ogni versione tra le due su cui ti trovi. (da 4.1 a 4.7).

non sono sicuro quale architettura di destinazione hai, quindi assicurati di controllare quelle sezioni specifiche in ciascuno dei documenti. Ma penso che tu voglia veramente dare uno sguardo allo "Build system improvements" e allo "Incompatible changes to the build system", che facciano anche una sezione specifica per il codice C che potrebbe essere utile rivedere.

1

Non ci sono abbastanza informazioni qui per dire con precisione cosa sta succedendo. Mi unisco a coloro che dicono che è improbabile che si tratti di un problema di versione del compilatore.

Questo errore si verifica (ovviamente) quando il compilatore rileva due dichiarazioni diverse con lo stesso nome. Non dovrebbe essere troppo difficile capire perché questo sta accadendo.

Controllare il makefile per trovare i file di intestazione internal.h e channel.h a cui si fa il riferimento. Le linee citate avranno un typedef o altra dichiarazione per channel_t lì. Lavora verso l'esterno da queste dichiarazioni per trovare indizi.

Devo supporre che uno o entrambi questi file siano nelle librerie che si stanno utilizzando. Se entrambi i codici internal.h e channel.h sono il tuo codice, esegui il debug del tuo codice!

Altrimenti ci sono molte possibilità. La più probabile sono

  1. preprocessore -D o #define bandiere Ed non sono corretti in modo che più le dichiarazioni vengono compilati condizionale, quando solo uno dovrebbe essere.

  2. Due diverse librerie o intestazioni standard e una libreria hanno un conflitto di nomi.

  3. Il proprio codice ha uno scontro con una libreria o intestazione standard. Se channel_t è un tipo definito, è un problema. Non è necessario definire i propri tipi che terminano con _t poiché sono riservati per l'implementazione.

Numero 1 di cui sopra può verificarsi in diversi modi, ma il più comune è errata configurazione di una libreria. Le librerie devono solitamente essere ./configure per il sistema operativo su cui vengono utilizzate. Se si configura in un Linux e si copia in un altro, si richiedono problemi come quello che si sta vedendo.

Il numero 2 potrebbe verificarsi su una linux e non sull'altra a causa delle differenze di versione della libreria. In questo caso, aggiornare la macchina con l'errore alle stesse versioni senza errore. Non dimenticare di eseguire ./configure.

Per il numero 3 la correzione è evidente. Cambia il nome del tuo tipo.

Vedo un channel.h e channel_t in Tor.La mia ipotesi è che tu stia usando Tor e osservi una errata configurazione di Tor sulla macchina con l'errore.

1

Questa non è una domanda per risolvere l'errore, ma una domanda generale sui compilatori .

C'è qualche indicatore che posso impostare per evitare questo in futuro.

Ogni versione specifica di un compilatore avrà i propri interruttori o flag.

Se la versione del compilatore è stata creata per accettare determinati parametri e uno di questi è quello necessario per evitare determinati controlli sul codice sorgente, allora sì c'è/sarebbe un modo per evitarlo in futuro.

Se la versione del compilatore, versione recente o futura, che si sta utilizzando non ha/accetta un interruttore per evitare/saltare determinati controlli sul codice sorgente, non c'è modo di evitarlo.

Problemi correlati