簡體   English   中英

sal annotation(prefast)強制執行可變參數的數量

[英]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()只被調用一次,而ij只增加一次。 在打印之前,浮點參數將轉換為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM