![](/img/trans.png)
[英]Compiling with different versions of gcc on ubuntu yields different results
[英]compiling source code on 2 different versions of gcc
我正在使用不同版本的gcc的2台不同機器上編譯我的源代碼。
cflags c89
-Wall -Wextra -Wunreachable-code -g -m32 -D_DEBUG -O0 -D_LARGEFILE64_SOURCE -D_REETRANT -D_THREAD_SAFE
一個是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
一個是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
我的fedora 18編譯沒有錯誤。 但是,在redhat 4機器上我遇到了一些錯誤。
channel.h:35: error: redefinition of typedef ‘channel_t’
internal.h:19: error: previous declaration of ‘channel_t’ was here
我認為錯誤只是一個循環問題。 但是,使用相同的代碼庫,在2台不同的機器上進行編譯真的可以使用2個不同版本的gcc來改變它們嗎?
我在考慮使用較新版本的編譯器會產生更多錯誤,因為較新的編譯器可能會更嚴格。
這不是解決錯誤的問題,而是編譯器的一般問題。
我可以設置任何標志以避免將來出現這種情況。 也許如果編譯這個版本的gcc這樣做,如果版本不兼容?
這取決於源代碼包含哪些標頭。 如果您要鏈接到外部庫,則可能是您的源代碼與舊系統上安裝的庫的版本不兼容。
如果源代碼不包含任何外部庫頭(C庫除外),則可能存在需要更改的預處理器指令。
編輯:
在Google搜索之后,看來channel_t
來自內核標頭。 您在兩台計算機上使用的內核版本相距甚遠。 如果代碼依賴於內核頭文件,則可能需要比Red Hat機器更新的內核版本。 您還沒有指定代碼是什么(它是設備驅動程序?),或者它包含的文件,因此很難說更多。
這是一個重復: 為什么“重新定義typedef”錯誤與GCC 4.3而不是GCC 4.6?
答案是更改了gcc以修改此檢查。
http://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=ce3765bf44e49ef0568a1ad4a0b7f807591d6412
有時,對語言中定義的行為的警告,但被認為是不良行為,被認為過於嚴格,因為警告中包含某些有用和/或無害的用例。 編譯器開發人員然后嘗試以相反的方式修復,即減少警告的數量。 在這種情況下,只有當第二個定義將typedef更改為不同但兼容的類型時,更改才會顯示警告。
其他當前的例子是剛才宣布的gcc 4.8中的-Wshadow。 在發行說明中,它表示如果函數名被另一個陰影,-Wshadow將不再發出警告。
請參閱: http : //gcc.gnu.org/gcc-4.8/changes.html
編輯:如何避免這種情況:刪除其中一個定義,或將其移至單獨的包含文件並刪除其他定義。
比較兩個系統中channel.h和internal.h的內容,得到不同的結果。 我懷疑問題是gcc的版本。 錯誤更有可能是這些文件隨時間發生代碼更改的結果,例如當一個系統具有較新版本的庫以及相關的頭文件而不是另一個時。
首先,讓我們談談你的問題。 我認為系統在一個系統上出錯的最可能原因是代碼不一樣; 您可能希望通過某個工具或diff
命令驗證這一點,以查找代碼庫中出現的任何細微更改。 通常,當我看到該錯誤類型的問題時,您會遇到以下情況:
typedef struct Foo* Fooptr;
在頭文件中,然后:
typedef struct Foo
{
int bar;
} *Fooptr;
在源文件中。 這意味着您可以在源中刪除typedef,它應該沒問題。 只是尋找的東西。
現在,如果它是 gcc
問題,解決問題的第二個選項是,可以在同一台計算機上安裝多個版本的gcc ,然后通過-v
選項指定要運行的gcc
的確切版本。 所以在你的Fedora 18機器上給4.1.2一個鏡頭可能是一個好主意。
另外要注意,如果使用-v
選項,但不指定版本的gcc
運行,你會得到(在標准錯誤輸出)執行運行編譯階段的命令。 這可能有助於了解正在發生的事情以及每台計算機上發生的情況之間是否存在任何重大差異。
好的,現在回答你的問題。 是的,有一些標志用於編譯gcc
“版本X”:對於初學者,有__VERSION__
預定義宏 ,這將向您返回版本號的const char *
。 這可能非常有用,但正如gcc文檔所述:
您不應該依賴具有任何特定形式的內容,但可以指望它至少包含版本號
盡管如此,我通常只看到一種輸出形式,如果我的gcc
版本是4.6.3-1ubuntu5
就像"4.6.3"
。
現在,如果你知道(或懷疑)你的一些代碼會引起特定版本的gcc
會導致錯誤您可以使用__GNUC__
, __GNUC_MINOR__
和__GNUC_PATCHLEVEL__
預定義宏“保護”自己:
這是一個簡短的剪輯 - 它在最高級別顯示如何使用它:
#if __GNC__ == 3
printf(“Hello version 3.x.x\n”);
#elif __GNC__ == 4
printf(“Hello version 4.x.x\n”);
#endif
因此,在版本為4.6.3的上述系統中,您將看到“Hello version 4.xx”消息。 然后你可以獲得更高級的功能並檢查顛覆:
#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
或者使用您自己的宏的更干凈版本:
#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
為了解決關於gcc
不同版本是否會產生不同錯誤的問題,你是正確的,在gcc
每個版本中都有更多的事情發生,有時情況會發生變化,所以你會看到不同版本的編譯器之間的差異。 最好的辦法是檢查你所在的兩個版本之間的發行說明。 (從4.1到4.7)。
我不確定您的目標架構是什么,因此請確保檢查每個文檔中的特定部分。 但我認為你真的想看看"Build system improvements"
和"Incompatible changes to the build system"
,他們還制作了一個特定於C代碼的部分,可以方便地查看。
這里沒有足夠的信息來准確說明發生了什么。 我和那些說它不太可能是編譯器版本問題的人一起加入。
當編譯器遇到同一名稱的兩個不同聲明時,顯然會發生此錯誤。 要弄清楚為什么會發生這種情況應該不難。
檢查makefile以查找正在引用的internal.h
和channel.h
頭文件。 引用的行將在那里有channel_t
的typedef
或其他聲明。 從這些聲明中向外工作以尋找線索。
我必須假設這些文件中的一個或兩個都在您正在使用的庫中。 如果internal.h
和channel.h
都是您自己的代碼,請調試您自己的代碼!
否則有很多可能性。 最有可能的是
預處理程序-D
或#define
ed標志不正確,因此只有一個應該是有條件地編譯多個聲明。
兩個不同的庫或標准頭和庫都有名稱沖突。
您自己的代碼與庫或標准標題發生沖突。 如果channel_t
是您定義的類型,那就是一個問題。 您不應該定義以_t
結尾的自己的類型,因為這些類型是為實現保留的。
上面的數字1可以通過多種方式發生,但最常見的是庫的配置錯誤。 通常必須為他們正在使用的操作系統./configure
庫。 如果您在一個Linux中配置並復制到另一個Linux,則會遇到類似您所看到的問題。
由於庫版本差異,2號可能出現在一個Linux而不是另一個上。 在這種情況下,請將帶有錯誤的計算機更新為與沒有錯誤的計算機相同的版本。 不要忘記運行./configure
。
對於3號,修復是顯而易見的。 更改您的類型名稱。
我在Tor中看到了channel.h
和channel_t
。 我的猜測是你正在使用Tor,並在錯誤的機器上查看Tor配置錯誤。
這不是解決錯誤的問題,而是編譯器的一般問題。
我可以設置任何標志以避免將來出現這種情況。
每個特定版本的編譯器都帶有自己的開關或標志。
如果創建編譯器版本是為了接受某些開關,並且其中一個是您需要避免對源代碼進行某些檢查的那個,那么是的/將來有一種方法可以避免它。
如果你使用的編譯器版本,最新版本或未來版本沒有/接受開關來避免/跳過對源代碼的某些檢查,那么就沒有辦法避免它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.