PRE32-C. 不要在觸發(fā)函數(shù)宏中使用預(yù)編譯指令
宏的參數(shù)中不能包含預(yù)編譯指令附鸽,比如 #define
, #ifdef
, 和#include
. 根據(jù)C語言標(biāo)準(zhǔn),6.10.3瞒瘸,第11段[ISO/IEC 9899:2011]坷备,這樣做會引起 未定義的行為
The sequence of preprocessing tokens bounded by the outside-most matching parentheses forms the list of arguments for the function-like macro. The individual arguments within the list are separated by comma preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate arguments. If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives, the behavior is undefined.
同時參見 未定義行為 93.
這個規(guī)則同樣適用于將預(yù)編譯指令作為任何函數(shù)的參數(shù),因為不知道函數(shù)是否是用宏實現(xiàn)情臭。這包括所有的標(biāo)準(zhǔn)庫函數(shù)省撑,比如 memcpy()
, printf()
, 和assert()
,因為不知道這些標(biāo)準(zhǔn)庫函數(shù)是否用宏實現(xiàn)(C11, 7.1.4俯在,第1段)竟秫。
不遵從規(guī)范的示例代碼
在這個不遵從規(guī)范的示例代碼中[GCC Bugs],編程人員使用了預(yù)處理指令來指定平臺相關(guān)的參數(shù)跷乐。然而鸿摇,如果memcpy()
是通過宏來實現(xiàn)的,那么這個代碼就會產(chǎn)生未定義行為劈猿。
#include <string.h>
void func(const char *src) {
/* Validate the source string; calculate size */
char *dest;
/* malloc() destination string */
memcpy(dest, src,
#ifdef PLATFORM1
12
#else
24
#endif
);
/* ... */
}
遵從規(guī)范的解決方案
#include <string.h>
void func(const char *src) {
/* Validate the source string; calculate size */
char *dest;
/* malloc() destination string */
#ifdef PLATFORM1
memcpy(dest, src, 12);
#else
memcpy(dest, src, 24);
#endif
/* ... */
}
風(fēng)險評估
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
PRE32-C | Low | Unlikely | Medium | P2 | L3 |
參考文獻
[GCC Bugs] | "Non-bugs" |
---|---|
[ISO/IEC 9899:2011] | 6.10.3, "Macro Replacement" |