【发布时间】:2011-06-13 21:10:37
【问题描述】:
我在为 64 位端口准备的一些 (C++) 代码中发现了与此类似的 sn-p。
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
}
虽然我严重怀疑这是否会在内存密集型应用程序中引起问题,但从理论上讲还是值得研究的,因为可能会出现类似的错误, 会导致问题。 (将上例中的n 更改为short,即使是小文件也可能溢出计数器。)
静态分析工具很有用,但它们不能直接检测到这种错误。 (反正还没有。)计数器n 根本不参与while 表达式,所以这不像其他循环那么简单(类型转换错误会消除错误)。任何工具都需要确定循环将执行超过 231 次,但这意味着它需要能够估计表达式 (pos = find(ch, start)) != npos 将评估为真的次数——这可不小!即使一个工具可以确定循环可以执行超过 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-1500 万行代码。)检查所有这些是不可行的,所以我对自动识别这类问题(即使它导致高误报率)的方法特别感兴趣。
【问题讨论】:
标签: c++ 64-bit portability 32bit-64bit