[英]sal annotation (prefast) to enforce number of variadic args
我有一個可變函數:
print_n_integers(7, 1, 2, 3, 4, 5, 6, 7);
int print_n_integers( unsigned int count, ... )
{
// use va_start etc.
}
我想從sal.h
使用Microsoft的SAL注釋,以便Visual Studio編譯器在參數數量與count
不匹配時注意到。 我可以通過這種方式強制count
:
int print_n_integers (
_Literal_ unsigned int count,
...
)
和Visual Studio至少有一些聰明才能應對printf()
,但有什么簡單的參數計數?
我想為您的問題提出一種不使用靜態分析的替代方法。
即使您可以獲得靜態分析的可變參數的計數,您仍然必須為每個調用提供正確的計數。 您還必須確保所有參數都是(或可以提升為)整數。
處理homogenouos類型列表的更自然,非變量方法是打印數組:
void print_nint(const int *arr, size_t n);
C99兼容編譯器可以使用復合文字在現場創建數組:
print_nint((int[]) {0, 8, 15}, 3);
此語法適合包裝在宏中:
#define print_int(...) \
print_nint((int[]){__VA_ARGS__}, \
sizeof((int[]) {__VA_ARGS__}) / sizeof(int))
此宏執行計數,您可以在沒有顯式參數計數的情況下使用它:
print_int(1, 2, 3.0, rand(), i++, j++);
可變參數的第二個擴展在sizeof
內部使用,而不是求值。 在上面的行中, rand()
只被調用一次,而i
和j
只增加一次。 在打印之前,浮點參數將轉換為int
。
Visual Studio在2013 RC中引入了復合文字,但舊版本不支持它們。 不幸的是,復合文字也會使代碼無法用於C ++編譯器。 對於這些情況,您可以重做宏來定義臨時數組:
#define print_int(...) { \
int PrintMe_[] = {__VA_ARGS__}; \
print_nint(PrintMe_, sizeof(PrintMe_) / sizeof(*PrintMe_)); \
}
但是,只有在void上下文中調用函數時,此策略才有效。
如果僅使用宏,則數組及其大小是一致的。 但是您可以發布底層實現並使用SAL注釋它:
void print_nint(_In_reads_(n) const int *arr, size_t n);
我不提倡無償使用宏,但在這種情況下,宏扮演模板的角色; 它可以減少危險的冗余。
不幸的是,在這種情況下,SAL目前沒有注釋。
對printf
/ scanf
/ scanf_s
類函數的支持被硬編碼到分析器中,並分別通過_Printf_format_string_
/ _Scanf_format_string_
/ _Scanf_s_format_string_
注釋進行訪問(對於特殊情況, _Printf_format_string_params_
/ _Scanf_format_string_params_
/ _Scanf_s_format_string_params_
)。 因此,您唯一的機會是游說代碼分析團隊為您的用例添加支持。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.