检测整数溢出

9
我正在使用一个大型的C库,其中一些数组索引是使用int计算的。我需要找到一种方法,在运行时捕获整数溢出,以便缩小到有问题的代码行。libc手册指出:

FPE_INTOVF_TRAP 整数溢出(在C程序中不可能,除非您以硬件特定的方式启用了溢出陷阱)。

然而,gcc选项-ffpe-trap表明这些只适用于FP数字?那么我如何启用整数溢出陷阱?我的系统是Xeon/Core2,gcc-4.x,Linux 2.6。
我已经查看了类似的问题,但它们都归结为修改代码。然而,我需要知道首先哪个代码存在问题。如果Xeons无法捕获溢出,哪些处理器可以?我还可以访问非emt64机器。
与此同时,我已经找到了一个专为llvm设计的工具:http://embed.cs.utah.edu/ioc/。然而,似乎没有针对gcc / icc的等效工具?

据我所知,没有x86处理器支持整数溢出陷阱。许多RISC CPU(例如Power和Sparc)以及较早的小型/大型机CPU(例如VAX)都支持此功能。 - Chris Dodd
我可以尝试使用Power,但周围没有VAX。 - Anycorn
4个回答

3

好的,我可能需要回答自己的问题。

我发现gcc有-ftrapv选项,快速测试确实证实了在我的系统上会捕获溢出。随着我学到更多信息,我会发布更详细的信息,因为它似乎是非常有用的工具。


2

无符号整数算术运算当然不会溢出。

使用有符号整数算术,溢出会导致未定义的行为;任何事情都可能发生。而且优化器越来越激进地优化溢出的内容。因此,您最好是避免溢出,而不是在发生时捕获它。考虑使用CERT的 "安全整数库"(那里引用的URL似乎已经消失/404了;我还不确定发生了什么)或Google的"安全整数操作"库。

如果必须要捕获溢出,则需要指定您感兴趣的平台(包括版本的O/S和编译器),因为答案将非常特定于平台。


1
我需要知道需要用 size_t 替换哪些操作。我在问题中指定了系统/编译器。 - Anycorn

2
你是否确切地知道溢出发生在哪一行?如果是这样,你可以查看汇编器的Carry标志位,如果所涉及的操作导致了溢出,这是CPU用于进行大数计算的标志位,在C级别不可用,但可能有助于您调试问题-或者至少给您一个机会做些什么。
顺便说一下,找到了这个链接(-ftrapv),它讨论了整数陷阱。也许这正是你要找的。

2
有没有可能在计数器上放置一个写入内存断点来帮助你? - Michael Dorgan
我不这么认为。在多个地方将int用于size_t的情况下,手动调试非常困难。 但我可能已经找到了一个解决方案。 - Anycorn

0

你可以在gcc中使用内联汇编来使用可能会生成溢出的指令,然后测试溢出标志以查看它是否实际发生:

int addo(int a, int b)
{
    asm goto("add %0,%1; jo %l[overflow]" : : "r"(a), "r"(b) : "cc" : overflow);
    return a+b;
overflow:
    return 0;
}

在这种情况下,它尝试添加ab,如果成功,就会跳转到overflow标签。如果没有溢出,它将继续执行,再次进行添加并返回结果。

这遇到了GCC的限制:内联asm块无法同时输出值和分支-- 如果没有这个限制,您就不需要第二个添加操作来实际获得结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接