2013-07-07 29 views

回答

1

#include <cmath>與任何庫都沒有關係,並且一切都與頭文件有關。假設你確實意味着如果你包含一個特定的頭文件,你想編譯失敗,你應該能夠利用GCC's support for specifying include directories through environment variables

爲此,請創建或編輯適當的環境文件。例如,如果您在Debian上使用GNU bash,則可以創建一個文件/etc/profile.d/gcc-include-dirs。在啓動shell時,/etc/profile.d中的所有內容都是可讀的,因此它將應用於在該點之後啓動的所有shell。 (絕對肯定,你可能需要註銷並重新登錄在一次,然後發出env | grep INCLUDE確認。)用你喜歡的編輯器創建一個這樣的文件,並添加以下代碼行:

export C_INCLUDE_PATH=/usr/local/include/fail:${C_INCLUDE_PATH} 
export CPLUS_INCLUDE_PATH=/usr/local/include/fail:${CPLUS_INCLUDE_PATH} 

確保文件每個人都可讀(chmod 644 /etc/profile/gcc-include-dirs),並且它由根(chown root:root /etc/profile/gcc-include-dirs)擁有。

如果您在特定時間只需要這種行爲,您還可以將該文件放在其他地方並簡單地source。在這種情況下,從有問題的shell註銷並重新登錄將會恢復GCC的正常行爲(您不需要從整個會話中註銷,只需要那個特定的shell實例)。在這種情況下啓動一個子shell並從該子shell中獲取文件也將很好地工作;完成後只需exit

然後創建一個文件/usr/local/include/fail/cmath,內容如下:

#error "Failing because you included 'cmath'" 

確保文件也就是任何人讀取,並通過超級用戶擁有。 #error及其邪惡的雙胞胎#warning分別發出致命錯誤和編譯警告,因此無論何時包含此文件,GCC都將遇到#error預處理程序指令,從而導致致命錯誤的發生,從而導致編譯失敗。

如果您想要爲單個編譯覆蓋此行爲,只需使用gcc的-I參數指定真實math.h所在目錄的路徑。由於-I優先於$C_INCLUDE_PATH$CPLUS_INCLUDE_PATH這意味着您隨後包含C庫的版本。例如,cc -o mathprogram -I/usr/include mathprogram.c將在中使用/ usr/include中的math.h,而不管/ usr/local/include/fail中的內容可能是什麼,因爲它首先在/ usr/include中顯示。因爲這隻影響編譯(並且只通過shell開始編譯),所以系統中已有的所有內容都將完全不受影響(除非它們對這兩個環境變量有一些奇怪的依賴關係)。

對於c*標頭,您可能還需要創建相應的*.h標頭,其內容與c*標頭的內容相同。這是因爲例如cmath可能簡單地映射到math.h(C中相同標題的名稱)。簡單地製作另一個文件,就像上面的文件一樣,但是反過來抱怨math.h。 (GCC並不在意,但它使診斷更容易)。您可能還需要將文件放在其他位置(我不確定包含CCC頭文件所需的目錄結構)。在這種情況下,find/-name cmath(或類似的東西)可以讓你瞭解在/ usr/local/include/fail下需要複製的結構。

請注意這不會阻止人們簡單地將頭文件的相關部分複製到他們自己的源代碼中;從編譯器的角度來看,沒有什麼不可思議的頭文件。取決於你想要保護什麼,這可能是一個問題。

+0

感謝您的回答。正在進行比賽,不能嘗試。但是,謝謝! –

1

簡單地使用預處理器符號來省略庫頭文件怎麼樣? 使用gcc選項-DDONT_WANT_LIBS進行編譯將失敗,因爲庫頭文件中缺少庫聲明。

#ifndef DONT_WANT_LIBS 
#include<specific_library_header.h> 
#endif 
    ... 
    ... 
+0

這不會是最佳的,因爲我正在編譯從我的參賽者進來的噸文件。 –

+2

這對我來說聽起來像學生(或參賽者或誰)應該(重新)實施某些事情而不是包括標準標題。然後這是一個快速檢查,以解決那些仍然包括它的問題。這不是從你自己的代碼中排除你自己的頭文件。 – Mario

+0

@Mario是的,我用cms來舉辦比賽。 –