2013-03-05 12 views
7

Kompiluję mój kod źródłowy na 2 różnych maszynach, które używają różnych wersji gcc.kompilowanie kodu źródłowego w 2 różnych wersjach gcc

CFLAGS C89

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

Jednym z nich jest 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 

I jedno jest 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 

Moi Fedora 18 kompiluje bez błędów. Jednak na maszynie redhat 4 dostaję błędy.

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

Myślę, że błąd jest tylko okrężnym problemem. Jednak przy tej samej podstawie kodu kompilowanie na 2 różnych komputerach naprawdę robi różnicę przy użyciu 2 różnych wersji gcc?

Myślałem, że przy użyciu nowszej wersji kompilatora wygeneruje więcej błędów, ponieważ nowszy kompilator może być bardziej ścisłe.

To nie jest kwestia rozwiązania błędu, ale ogólne pytanie dotyczące kompilatorów.

Czy są jakieś flagi, które mogę ustawić, aby tego uniknąć w przyszłości. Może jeśli kompiluje się na tej wersji gcc, jeśli wersje nie są kompatybilne?

+1

Tak, różne kompilatory/wersje/flagi mogą dawać różne wyniki, szczególnie. w kodzie # # ifdef'. –

+0

jeśli chodzi o "flagi, które mogę ustawić, aby tego uniknąć w przyszłości", czy moja odpowiedź na to pozwala, czy też myślisz o czymś innym? – Mike

+0

niektóre przydatne informacje byłyby miłe, bardziej prawdopodobne jest, że będą zawarte w nagłówku innym w systemie niż w kompilatorze, ale nigdy nie wspomnisz, gdzie są channel.h lub internal.h i jak są uwzględniane. otaczające linie wokół miejsca, w którym pojawia się channel_t, również by się przydały ... przynajmniej do ifdefs. Twoja świetlówka CFLAG bez niczego definiuje średnią absolutnie nic. – technosaurus

Odpowiedz

4

To duplikat: Why "Redefinition of typedef" error with GCC 4.3 but not GCC 4.6?

odpowiedź brzmi, że gcc został zmieniony, aby zmodyfikować ten czek.

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

Czasami ostrzeżenia dla zachowania zdefiniowane w języku, ale uznał, złe praktyki, są uważane za zbyt surowe, ponieważ niektóre pożyteczne i/lub nieszkodliwe przypadki użycia są zawarte w ostrzeżeniu. Twórcy kompilacji następnie próbują naprawić w przeciwny sposób, czyli zmniejszając liczbę ostrzeżeń. W takim przypadku zmiana spowodowała pojawienie się ostrzeżenia tylko wtedy, gdy druga definicja zmieniła typedef na inny, ale zgodny typ.

Innym aktualnym przykładem jest -Wshadow w gcc 4.8 właśnie ogłoszone. W notatce wydania jest napisane, że -Wshadow nie będzie ostrzegał, jeśli nazwa funkcji jest zacieniona przez inną.

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

Edycja: jak można tego uniknąć: albo usunięcie jednej z definicji, lub przenieść go do oddzielnego zawierać plik i usunąć obie inne definicje.

10

Zależałoby od tego, jakie nagłówki są dołączane przez kod źródłowy. Jeśli łączysz się z bibliotekami zewnętrznymi, być może kod źródłowy jest niekompatybilny z wersją biblioteki zainstalowanej w starszym systemie.

Jeśli kod źródłowy nie zawiera żadnych zewnętrznych nagłówków bibliotek (z wyjątkiem biblioteki C), wówczas mogą istnieć dyrektywy preprocesora, które wymagają zmiany.

EDIT:

Po Google wyszukiwania, wydaje się, że channel_t jest z nagłówka jądra. Używasz wydania jądra w dużej odległości na dwóch maszynach. Jeśli kod zależy od pliku nagłówkowego jądra, może wymagać wersji jądra nowszej niż na maszynie Red Hat. Nie określiłeś, co to jest kod (czy jest to sterownik urządzenia?) Lub jakie pliki zawiera, więc trudno powiedzieć więcej.

+0

Twoje odpowiedzi są miłe, więc daj +1 "miłym" tagiem. –

+0

@GrijeshChauhan: dziękuję! – teppic

4

Porównaj zawartość channel.h i internal.h w dwóch systemach, w których uzyskujesz różne wyniki. Wątpię, aby problem dotyczył wersji gcc. Bardziej prawdopodobne jest, że błędy są wynikiem zmian kodu w tych plikach w czasie, np. Gdy jeden system ma nowszą wersję biblioteki i powiązane pliki nagłówkowe niż inne.

1

Po pierwsze, porozmawiajmy trochę o twoim problemie. Myślę, że najbardziej prawdopodobną przyczyną błędu systemu w jednym systemie jest drugi kod, który nie jest identyczny; możesz to sprawdzić za pomocą jakiegoś narzędzia lub polecenia diff, aby wyszukać subtelne zmiany, które pojawiły się w bazie kodu. Zwykle, gdy widziałem problemy z tego typu błędów, masz coś takiego:

typedef struct Foo* Fooptr; 

w pliku nagłówka, a następnie:

typedef struct Foo 
{ 
    int bar; 
} *Fooptr; 

w pliku źródłowym. Co oznacza, że ​​możesz po prostu upuścić typedef w źródle i powinno być OK. Po prostu coś do znalezienia.

Teraz jeśli jestgcc problem, druga opcja, aby rozwiązać Twój problem jest, to możliwe have multiple versions of gcc on the same computer a następnie określić dokładną wersję gcc do uruchomienia z pomocą opcji -v. Dobrym pomysłem jest nadanie 4.1.2 ujęcia na maszynie Fedory 18.

Inna uwaga, jeśli używasz opcji -v, ale nie określić wersję gcc uruchomić, dostaniesz (na wyjście stderr) poleceń wykonywanych uruchomić etapy kompilacji. Może to być przydatne, aby zobaczyć, co się dzieje i czy istnieją istotne różnice między tym, co dzieje się na każdym komputerze.


OK, teraz na twoje pytania. Tak, istnieją flagi do kompilacji na "wersji X" z gcc: Na początek jest __VERSION__ Predefined Macro, to spit z powrotem do ciebie const char * numeru wersji. Może to być bardzo przydatne, ale jak gcc dokumentacji stwierdza:

Nie należy polegać na jego zawartość mających żadnej szczególnej formy, ale może liczyć na zawierać co najmniej numer wersji

Mimo to zazwyczaj widziałem tylko jedną formę wyjścia, która jest podobna do "4.6.3", jeśli moja wersja gcc to 4.6.3-1ubuntu5.

Teraz jeśli wiesz (lub podejrzany), że część kodu spowoduje konkretnej wersji gcc powodować błędy można użyć __GNUC__, __GNUC_MINOR__ i __GNUC_PATCHLEVEL__ predefiniowanych makr do „chronić” siebie:
Oto krótki wycinek-to pokazano na najwyższym poziomie, jak go używać:

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

więc na powyższym układzie, gdzie wersja to 4.6.3 chcesz zobaczyć komunikat „Hello wersja 4.xx”. Następnie można uzyskać bardziej zaawansowane i sprawdzić subversions także:

#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 

Albo czystszą wersję tego za pomocą własnego makro:

#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 

Aby zaadresować pytanie czy różnych wersjach gcc będzie generował różne błędy, masz rację, że w każdym wydaniu gcc dzieje się więcej, a czasem coś się zmienia, więc zobaczysz różnice między różnymi wersjami kompilatora. Najlepiej jest sprawdzić informacje o wydaniu dla każdej wersji pomiędzy tymi dwoma, na których jesteś. (od 4,1 do 4,7).

nie jestem pewien jaka masz architekturę docelową, więc upewnij się, że sprawdzasz te sekcje w każdym z dokumentów. Ale myślę, że naprawdę chcesz rzucić okiem na "Build system improvements" i "Incompatible changes to the build system", tworzą także sekcję specyficzną dla kodu C, która może być przydatna do przejrzenia.

1

Nie ma wystarczających informacji, aby dokładnie powiedzieć, co się dzieje. Łączę się z tymi, którzy twierdzą, że nie jest to problem z wersją kompilatora.

Ten błąd występuje (oczywiście), gdy kompilator napotka dwie różne deklaracje dla tej samej nazwy. Nie powinno być zbyt trudno zrozumieć, dlaczego tak się dzieje.

Sprawdź plik Makefile, aby znaleźć pliki nagłówkowe internal.h i channel.h, które są przywoływane. Cytowane wiersze będą miały typedef lub inną deklaraję dla channel_t tam. Pracujcie na zewnątrz od tych deklaracji po wskazówki.

Muszę założyć, że jeden lub oba te pliki znajdują się w bibliotekach, z których korzystasz. Jeśli zarówno internal.h jak i channel.h są twoim własnym kodem, debuguj własny kod!

W przeciwnym razie istnieje wiele możliwości. Najbardziej prawdopodobne są

  1. preprocesora -D lub #define ed flagi nie są prawidłowe, tak że wielokrotne deklaracje są warunkowo skompilowane kiedy tylko trzeba być.

  2. Dwie różne biblioteki lub standardowe nagłówki i biblioteka mają konflikt nazwy.

  3. Twój własny kod ma konflikt z biblioteką lub standardowy nagłówek. Jeśli channel_t jest zdefiniowanym typem, jest to problem. Nie powinieneś definiować swoich własnych typów kończących się na _t, ponieważ są one zarezerwowane dla implementacji.

Numer 1 może występować na kilka sposobów, ale najczęstszą jest błędna konfiguracja biblioteki. Biblioteki muszą zwykle mieć numer ./configure ed dla systemu operacyjnego, na którym są używane. Jeśli konfigurujesz w jednym systemie Linux i kopiujesz do innego, pytasz o problemy, takie jak ten, który widzisz.

Liczba 2 może wystąpić na jednym linuksie, a nie z powodu różnic w wersji bibliotecznej. W takim przypadku zaktualizuj maszynę o błąd do tych samych wersji, co wersja bez błędu. Nie zapomnij uruchomić ./configure.

W przypadku numeru 3 poprawka jest oczywista. Zmień nazwę swojego typu.

Widzę channel.h i channel_t w Tora.Domyślam się, że używasz Tora i patrzysz na błędną konfigurację Tora na komputerze z błędem.

1

To nie jest kwestia do rozwiązania błędu, ale ogólne pytanie na kompilatory .

Czy są jakieś flagi, które mogę ustawić, aby tego uniknąć w przyszłości.

Każda określona wersja kompilatora będzie dostarczana z własnymi przełącznikami lub flagami.

Jeśli została utworzona wersja kompilatora, aby zaakceptować pewne przełączniki, a jedną z nich jest ta, której należy unikać w celu sprawdzenia kodu źródłowego, to tak, istnieje/byłby sposób uniknięcia jej w przyszłości.

Jeśli wersja kompilatora, najnowsza lub przyszła wersja, której używasz, nie ma/nie akceptuje przełącznika, aby uniknąć/pominąć pewne sprawdzenia kodu źródłowego, nie można tego uniknąć.

Powiązane problemy