我想讓人們停止使用像sprintf
這樣的函數,因爲它被認爲是不安全函數。如果在代碼中使用sprintf
或其他任何技巧,是否存在編譯錯誤的編譯方式?編譯方式停止使用某些C系統調用
回答
#define sprintf COMPILE_TIME_ERROR
#define COMPILE_TIME_ERROR switch(0){case 0:case 0:;}
int main(void) {
char hi[50];
sprintf(hi,"hi");
return 0;
}
編譯器的輸出將是這樣的:
prog.c: In function ‘main’:
prog.c:6: error: duplicate case value
prog.c:6: error: previously used here
儘管它很糟糕,但它適用於所有編譯器。 +1。 – ArjunShankar 2012-07-30 10:24:12
+1這就是我要發佈的答案。編譯時間斷言是不可思議的事情,並不經常使用imo。 – Mawg 2012-07-30 10:24:45
#error有什麼問題... – thang 2015-02-22 22:43:16
是。
您將LD_PRELOAD設置爲庫列表,並且所有這些庫都將先於其他庫加載。您可以定義您需要覆蓋的函數,將該文件設爲共享庫,將該變量設置爲該lib的名稱,然後運行您的可執行文件。
GCC supports this sort of thing與#pragma GCC poison
。使用該標識符後跟一列標識符將導致在程序中使用任何的標識符來引發錯誤。例如,該程序將不編譯:
#include <stdio.h>
#pragma GCC poison fprintf sprintf
int main (void)
{
char foo[100];
sprintf (foo, "bar");
return 0;
}
如果宏定義前pragma
擴展到標識符,則該次數將不再中毒。例如,該程序可以編譯:
#include <stdio.h>
#define print_to_string sprintf
#pragma GCC poison sprintf
int main (void)
{
char foo[100];
print_to_string (foo, "bar");
return 0;
}
不是一個答案,但我太愚蠢知道如何發佈格式代碼的答覆。
IMO,@myrkos給出了這個問題的正確答案。
但是,他提到編譯時錯誤,我也想概括一個compile time assert
(又名static assert
)。
谷歌這些條款,你會得到一堆建議。取決於你的編譯器,有些編譯器會給出比其他編譯器更令人滿意的錯誤信息,所以建一個小的測試程序。我個人(因人而異)喜歡這個一個與海灣合作委員會(道歉原作者,因爲我不記得我是從「借」 - 這是很久以前,它仍然成爲我很好):
/** A "static assert", which checks a condition at compile time, rather
* than run time. The sooner problems are found, the sooner they can be fixed
* (and with less effort).
*
* Use this one where you don't even want the code to begin running
* if something is wrong. If you don't use this, you need a test case,
* but sometimes tests don't get run, so use this for the sort of thing
* that should never be released to the customer (or even the test department).
*
* Example: ASSERT_AT_COMPILE_TIME(1==2), one_does_not_equal_two);
* gives this error message under GNU on Linux:
* size of array one_does_not_equal_two is negative
*
* Note: this is very useful checking the size of user defined types, like uint64_t
* or for doing things like this:
*
* struct foo {
* int x;
* int y;
* };
* ASSERT_AT_COMPILE_TIME(offsetof(struct foo, y) == 4, y_is_at_offset_4);
*/
#define ASSERT_CAT1(x) ASSERT_CAT ## x
#define ASSERT_CAT0(x) ASSERT_CAT1(x)
#define ASSERT_AT_COMPILE_TIME(expression, message) \
struct ASSERT_CAT0(__LINE__) {char message[2*!!(expression)-1]; }
其他人提到觸發編譯錯誤。
不幸的是,如果你想區分錯誤,錯誤信息往往不是非常明確。好事做的是有一個名字一個未定義的對象嵌入了錯誤信息,如:
#define sprintf (do_not_use_sprintf_call = 0)
所以當sprintf
被稱爲gcc
錯誤信息將更加明確:
tst.c: In function `main':
tst.c:11: error: `do_not_use_sprintf_call' undeclared (first use in
this function)
tst.c:11: error: (Each undeclared identifier is reported only once
tst.c:11: error: for each function it appears in.)
請注意,使用C11,您也可以使用靜態聲明來獲得自己的錯誤消息:
#define sprintf _Static_assert(0, "do_not_use_sprintf_call")
- 1. 用C編譯系統
- 2. 防止某些類使用屬性調用某些方法
- 3. 以編程方式調用C#編譯器編譯C#代碼
- 4. C#系統停止托盤應用
- 5. 停止編輯框中的某些鍵
- 6. 調用C「系統」 ++
- 7. 如何編譯C文件與系統調用
- 8. 使用execve系統調用C編程網絡編程
- 9. 「使用系統」;「產生編譯錯誤
- 10. 使用系統函數編譯文件
- 11. C編程 - Stat系統調用 - 錯誤
- 12. 如何通過庫調用C編譯器而不是通過系統調用?
- 13. 系統()調用用C
- 14. 停止系統進入'備用'
- 15. 使用某些linq表達式(moq)調用驗證方法
- 16. 在某些系統調用中同步兩個進程
- 17. 以編程方式啓動和停止Spring集成中的某些IntegrationFlows?
- 18. Linux系統調用getifaddr C++
- 19. 與c的系統調用
- 20. 系統調用在C++中
- 21. linux系統調用getpeername C++
- 22. Unix系統調用Objective-C
- 23. fork()系統調用c
- 24. 在C系統調用
- 25. C編譯程序使用哪些段?
- 26. Java方法停止調用
- 27. 如何在C中停止預編譯?
- 28. -MS系統Visual Studio C++編譯器
- 29. 使用C++編寫操作系統
- 30. 如何使用C/C++以編程方式檢查Windows系統文件夾?
哪個編譯器?我已經看到至少有一個編譯器(我認爲這是一個微軟,但不記得確切)警告這樣的事情。作爲一般慣例,我傾向於爲每個編譯器提供嚴格的警告。 – Mawg 2012-07-30 10:02:51
正如@Mawg所說,編譯時具有最高的警告級別,並將警告作爲錯誤提供此功能。在Visual Studio中,編譯器標誌是'/ W4/WX',而gcc(I _think_)是'-Werror -Wall'。 – hmjd 2012-07-30 10:08:40
你的意思是「不健康」嗎?我認爲這是「sfinae」。但是你需要爲此升級到C++。 – 2012-07-30 10:20:10