2016-06-28 51 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++; 
    } 

因此,你有你的序列点之间的明显区别。