抓住c bool的错误用法

pla*_*hos 20 c c99

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

typedef int bool;
#define false 0
#define true 1
Run Code Online (Sandbox Code Playgroud)

现在切换到C99布尔

#include <stdbool.h>
Run Code Online (Sandbox Code Playgroud)

但在该项目有地方的布尔的一个不好的用法.我知道std bool表现不同.例如

bool t;

t=2;
if ( t == true)
    printf("True!\n");
else
    printf("False!\n");
Run Code Online (Sandbox Code Playgroud)

将返回True!与stdbool.h和假的!与#define模拟.

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

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

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

 static inline bool
 mbuf_len (const struct mbuf_set *ms)
 {
   return ms->len;
 }
Run Code Online (Sandbox Code Playgroud)

tep*_*pic 2

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

typedef enum {false, true} bool;
Run Code Online (Sandbox Code Playgroud)

这仍然允许代码编译而不会出现错误(因为它定义良好),但您可以强制编译器或分析器发出警告。例如,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;
Run Code Online (Sandbox Code Playgroud)

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

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

如果没有_Bool类型,就无法让语言本身直接为您执行此操作,因为没有可比较的类型,并且您实际上会要求它允许2 == 1返回 true。

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

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

bool b = rand() % 100;

if (BOOL(b) == true) ...
Run Code Online (Sandbox Code Playgroud)

无论使用stdbool还是typedef.