2016-06-28 73 views
2

我在下面的C代碼運行靜態代碼分析2004年MISRA和MISRA 2012:雙方都有副作用?

BOOL_TYPE Strings_Are_Equal(const char *s1, const char *s2) 
{ 
    BOOL_TYPE result = True; 
    const char *str1 = s1; 
    const char *str2 = s2; 

    if (NULL == s1 || NULL == s2) 
    { 
    result = False; 
    } 
    else if (strlen(s1) != strlen(s2)) 
    { 
    result = False; 
    } 
    else 
    { 
    while (*str1 != 0) 
    { 
     if(tolower(*str1++) != tolower(*str2++)) 
     { 
     result = False; 
     break; 
     } 
    } 
    } 

    return result; 
} 

,並得到了來自PC-皮棉報告以下結果: enter image description here

有人可以請解釋如何第58行和第66行代碼有副作用,我應該如何糾正它?

回答

6

當使用C標準的正式定義時,調用函數可能會引起副作用

strlen(s1) != strlen(s2)的具體情況下,這些功能中沒有任何內容可能會造成傷害。用例如內部變量static來實現它們是沒有意義的。但是,如果存在這樣的內部變量,則根據首先執行哪個函數調用,評估順序可能會產生不同的結果。這可能是警告背後的原因。

tolower(*str1++) != tolower(*str2++)的情況下,++操作符有兩個函數調用副作用和兩個可變分配副作用,單個表達式總共有4個副作用。即使這種特殊情況是安全的,但這樣的代碼是危險的,因爲它可能取決於評估順序,甚至完全沒有序列化(如i=i++;),這將是一個嚴重的錯誤。

通過將函數結果存儲在臨時變量中解決此問題。永遠不要混用++與其他運營商,因爲這是既危險,毫無意義,並通過另一MISRA規則禁止:

MISRA-C:2004年第12.13

遞增(++)和遞減( - )運算符不應與表達式中的其他運算符混合使用 。

+0

正確答案imo。自從你指出我最初忘記的內容以來,我給了你一個贊成票。 (它一定是被驅動器downvoting) – 2501

+0

拒絕投票的理由?缺乏MISRA規則和C標準的引用?我在答案中找不到任何錯誤。 – Lundin

1

作爲附加到倫丁的出色答卷,在MISRA兼容的做法是:

while (*str1 != 0) 
    { 
     // Condition should be a single sequence point 
     // ... with no side effects 
     if (tolower(*str1) != tolower(*str2)) 
     { 
     result = false; 
     break; 
     } 

     // Now increment pointers 
     *str1++; 
     *str2++; 
    } 

因此,你有你的序列點之間的明顯區別。