如何发现难以捉摸的64位可移植性问题?
|
我正在为64位端口做准备的某些(C ++)代码中找到与此类似的代码段。
int n;
size_t pos, npos;
/* ... initialization ... */
while((pos = find(ch, start)) != npos)
{
/* ... advance start position ... */
n++; // this will overflow if the loop iterates too many times
}
尽管我严重怀疑这实际上甚至会在内存密集型应用程序中引起问题,但从理论的角度来看还是值得研究的,因为类似的错误可能会浮出水面,从而引起问题。 (在以上示例中,将“ 1”更改为“ 2”,即使是小文件也可能使计数器溢出。)
静态分析工具很有用,但它们无法直接检测到此类错误。 (无论如何,还没有。)计数器n
根本不参与ѭ4so表达式,因此,它不像其他循环那么简单(在这里,类型转换错误使错误消失了)。任何工具都需要确定该循环将执行超过231次,但这意味着它需要能够估计表达式(pos = find(ch, start)) != npos
将被评估为true的次数-不小的成就!即使工具可以确定该循环可以执行超过231次(例如,因为它识别出find
函数正在处理字符串),它如何知道该循环执行的次数不会超过264次,因此溢出size_t
值吗?
似乎很清楚,要最终确定并纠正这种错误需要肉眼观察,但是是否存在可以消除这种错误以便可以手动检查的模式?我应该注意哪些类似的错误?
编辑1:由于short
,int
和long
类型本质上是有问题的,可以通过检查这些类型的每个实例来发现这种错误。但是,考虑到它们在传统C ++代码中无处不在,我不确定这是否适用于大型软件。还有什么可以解决这个错误?每个while
循环是否都可能会出现这种错误? (for
循环当然不能幸免!)如果我们不处理short
这样的16位类型,这种错误有多严重?
编辑2:这是另一个示例,显示此错误如何在for
循环中出现。
int i = 0;
for (iter = c.begin(); iter != c.end(); iter++, i++)
{
/* ... */
}
从根本上说,这是同样的问题:循环指望永远不会直接与更大类型交互的变量。该变量仍然可以溢出,但是没有编译器或工具检测到强制转换错误。 (严格来说,没有。)
编辑3:我正在使用的代码很大。 (仅用于C ++的代码行为10-15百万行。)检查所有代码都是不可行的,因此我对识别此类问题的方式特别感兴趣(即使它会导致很高的假阳性率)费率)。
没有找到相关结果
已邀请:
3 个回复
邵酮
,ѭ9or或
是警告符号,因为标准中未定义这些类型的范围。大多数用法应在
中更改为新的
类型,并将处理序列化为
。好吧,实际上这些
类型应该用于
种新的特定于应用程序的类型。 这个例子确实应该是:
这表示了行数可以容纳32位的设计假设,并且如果设计要求发生变化,也可以轻松地固定代码。
寇剩
旗低饶彤