2017-08-09 71 views
1

示例代碼:爲什麼gcc和clang默默地允許一個標準的包含文件重新定義宏?

#define PROT_NONE 99 
#include <sys/mman.h> 

GCC和鐺允許上面的代碼片段來編譯; PROT_NONE宏是從sys/mman.h中重新定義的,沒有任何警告。看看實際的頭文件,沒有#undef會允許重定義。

這看起來像一個問題 - 雖然這種情況顯然是設法顯示問題,但似乎我的代碼和系統頭文件之間的標識符衝突可以默默忽略。 PROT_NONE的系統標題定義會覆蓋我的定義,甚至不會提醒我存在潛在的問題。這似乎是某種特定的系統頭文件;如果我自己嘗試重新定義,我會得到適當的錯誤。

我的問題基本上是雙重的:

  • 有誰知道背後允許這種行爲的動機是什麼?
  • 是否有任何命令行開關會導致編譯階段失敗?

回答

3

發生了什麼事/動機

在這兩個GNU和鐺,警告抑制系統頭。

clang user manual只是聲明是這樣的:當它們出現在系統頭

警告被抑制。

...但gnu c preprocessor manual給出了以下理由:

頭文件聲明接口,操作系統和運行時庫往往不能寫在嚴格符合C.因此,GCC給出了系統中發現的代碼接頭特殊治療。

緩解命令行

上是否有任何命令行開關,將導致這在編譯階段失敗?

是的。使您的系統標題爲非系統標題。

在clang中,只能使用--no-system-header-prefix x/y/z來做到這一點,其中x/y/z是從所有系統目錄開始匹配的模式。例如,在你的情況下,你可以使用--no-system-headers sys;或者你可以選櫻桃:--no-system-headers sys/mm(通過sys子目錄包含的系統目錄中以mm開頭的所有文件;它只是一個前綴模式,而不是目錄規範)。

在gcc中,這有點竅門。默認情況下,系統標題只是系統目錄中的標題,並且無法將特定目錄排除爲系統目錄。但是,您可以使用-nostdinc來丟棄所有系統目錄,並將其作爲常規包含目錄重新添加。例如:

gcc -nostdinc -I/usr/include -I/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include ... 

您需要-nostdinc; -I進入系統包含路徑的路徑只會被忽略。

+0

感謝您的叮噹聲緩解;我測試了它,它適用於我的目的。 –

2

GCC suppresses warnings in system headers默認情況下。原因是用戶通常無法對這些標題生成的警告進行任何操作,因爲他們無法編輯代碼來修復這些警告。您可以使用-Wsystem-headers啓用這些警告。

對於你的具體例子,通過系統頭重新定義一個未在系統頭中定義的宏,GCC甚至可能會警告-Wno-system-headers(它現在有基礎結構可以這樣做)。有人已經提交了RFE:

+0

感謝您提供RFE的鏈接。這有助於我理解競爭性的論點。 –

相關問題