在一个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;
}
答案 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)
很抱歉,写评论很长,所以这不是答案:
我认为您必须搜索所有文件中的true
,false
等字词,并查看其使用情况。
IMO,使用自动化工具可能会遇到这个问题:
int x = true;
int y = 8;
//...
if (x == y) // `true` is not near `if` statement
{
//...
我更喜欢手动代码审核,但这可能非常耗时。
所有其他建议,例如取消定义bool
,true
,false
,...以使编译器出错,只是简单搜索的复杂方式。
如果编译器说:
“你在xyz行有一个未定义的标识符'true'”
好的,搜索工具说:
“你在zyx行有'真'字”
我更喜欢第二种方式。