问题描述
|
我正在为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百万行。)检查所有代码都是不可行的,因此我对识别此类问题的方式特别感兴趣(即使它会导致很高的假阳性率)费率)。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)