抓住c bool的错误用法

时间:2013-03-11 12:55:58

标签: c c99

在一个C项目中(OpenVPN是有问题的项目,提交4029971240b6274b9b30e76ff74c7f689d7d9750)我们有一个模拟bool

typedef int bool;
#define false 0
#define true 1

现在切换到C99 bool

#include <stdbool.h>

但是在项目中,某处对bool的使用不当。我知道std bool表现不同。例如。

bool t;

t=2;
if ( t == true)
    printf("True!\n");
else
    printf("False!\n");

将返回True!与stdbool.h和False!使用#define仿真。

我的问题有没有办法找到与stdbool和模拟bool行为不同的代码部分?也许某些编译器标志我忽略了或者是一个好的llvm或gcc中间格式可以分化?

它没有上面例子那么简单,但必须是不容易看到的东西。绝对不是== true。

更新 我们发现了这个问题(mbuf_set有一个int成员len)。这有点愚蠢,但问题仍然是如何抓住这些。我很惊讶整数溢出检查不会发现这样的事情:

 static inline bool
 mbuf_len (const struct mbuf_set *ms)
 {
   return ms->len;
 }

2 个答案:

答案 0 :(得分:2)

您所描述的用法类型是正确的,定义明确的行为。所以编译器不会产生任何警告。解决此问题的一种可能方法是更改​​typedef

typedef enum {false, true} bool;

这仍然允许代码编译时没有错误(因为它已经很好地定义),但是你可以强制从编译器或分析器发出警告。例如,clang会使用-Weverything选择此类内容:

$ clang -o a a.c -Weverything
a.c:7:11: warning: integer constant not in range of enumerated type 'bool'
      [-Wassign-enum]
        bool n = 2;

当然这不会进行任何运行时检查。它仍然允许将typedef bool变量更改为0或1之外的其他变量(例如,通过函数调用或在表达式中)。检测这些实例的唯一方法是使用调试器。

stdbool.h中的true和false宏仅设计为_Bool类型。这是因为这种类型只能保存值0和1;您分配的任何非0值都存储为1.因此,对于仅布尔类型,保证true和false宏有效。

如果没有_Bool类型,就没有办法让语言本身直接为你做这个,因为没有类似的类型,你实际上要求它允许2 == 1返回true

有几种方法可以实现相同的行为,例如在每个使用变量BOOL(n)的实例中使用诸如n的宏,以确保其值仅为0或1。这样,无论是_Bool使用int还是n,您都会得到相同的结果。例如:

#define BOOL(n) ((n) != 0 ? 1 : 0 )

bool b = rand() % 100;

if (BOOL(b) == true) ...

无论是使用stdbool还是typedef,这都会有效。

答案 1 :(得分:0)

很抱歉,写评论很长,所以这不是答案:

我认为您必须搜索所有文件中的truefalse等字词,并查看其使用情况。

IMO,使用自动化工具可能会遇到这个问题:

int x = true;
int y = 8;

//...

if (x == y) // `true` is not near `if` statement
{
//...

我更喜欢手动代码审核,但这可能非常耗时。



所有其他建议,例如取消定义booltruefalse,...以使编译器出错,只是简单搜索的复杂方式。 如果编译器说:

  

“你在xyz行有一个未定义的标识符'true'”

好的,搜索工具说:

  

“你在zyx行有'真'字”

我更喜欢第二种方式。