3

我們正在Linux內核編寫代碼,所以儘可能地嘗試一下,我無法使PC-Lint/Flexelint在Linux內核代碼上工作。太多的內置符號等,但這是一個側面問題。使用編譯器警告捕獲常量1左移的溢出?

我們有任何數量的編譯器,以gcc開頭,但也有其他編譯器。隨着時間的推移,他們的警告選項變得越來越強大,他們的靜態分析工具也變得非常強大。

這是我想要捕捉的。是的,我知道它違反了代碼審查中容易理解的一些事情,比如「沒有幻數」和「小心位移」,但這只是在您碰巧看到代碼段時。無論如何,這裏是:

unsigned long long foo; 
unsigned long bar; 

[... lots of other code ...] 

foo = ~(foo + (1<<bar)); 

進一步更新的問題描述 - 即使酒吧限於16,仍然是一個問題。澄清,這個問題是隱式的int類型的常量,它是非計劃的,使得複雜表達式違反了所有計算都以相同大小和符號執行的規則。

問題:'1'不長,但作爲一個小值常量,默認爲int。因此,即使bar的實際值永遠不會超過16,那麼(1<<bar)表達式也會溢出並破壞整個計算。

可能正確的解決方案:改爲寫入1ULL。

是否有一個衆所周知的編譯器和編譯器警告標誌指出這(修訂)的問題?

+0

無論int的大小是多少,如果bar太大,那麼shift是不確定的(我認爲,某種壞的,反正)。你似乎在要求編譯器警告你關於一個變量的第二個操作數來移動一個int。但是你說問題是'1'不長:你是否想要長時間沒有變化的變化警告?我不明白爲什麼編譯器編寫者會期望這個警告是有用的,關於<<變量的第二操作數的一般警告會導致大量的誤報。 – 2009-07-16 21:16:04

+0

@onebyone:假設`int`是32位,`long long`是64,`〜(foo +(1 << bar))`只適用於'0 <= bar <32`,而`〜(foo + (1LL << bar))`適用於`0 <= bar <64`。我假設OP在寫前者而不是後者時要警告。 – ephemient 2009-07-17 03:15:39

回答

1

我不確定你認爲用什麼標準來標記 這個結構是否可疑。如果bar的值與int的大小(以位爲單位)一樣大,但通常編譯器 不知道,則顯然存在 錯誤。 從一個啓發式的點,缺陷調查工具,具有良好的圖案,以可能的錯誤從 正常結構分離 關鍵是要避免太多的假 陽性(它使用戶討厭的工具,並拒絕 使用它) 。

在我的網址標誌

開源工具的邏輯由數小於該類型的大小 的變化,但它主要是關鍵性嵌入式軟件驗證 工具和期待,如果你有很多工作 以得體呢打算在它的鏈接結構和其他困難的Linux內核 上使用它。