如何在C++中检测溢出?

5
我想知道在C++程序运行时是否有一种方便的方法来检测任何默认数据类型变量是否发生溢出?所谓方便,是指不需要每次值改变时编写代码来跟踪每个变量是否在其数据类型范围内。如果无法实现此操作,您会怎么做?
例如:
float f1=FLT_MAX+1;
cout << f1 << endl;

在使用"gcc -W -Wall"编译或运行时,都没有任何错误或警告。

谢谢和问候!


我猜你可能可以设置一个中断处理程序来完成这个任务?假设溢出实际上会生成一个中断。正如你所看到的,我只是在猜测,因此将其作为评论而不是答案添加。 - korona
3
是不是更好编写代码来预防(或使其难以发生)溢出,而不是试图在发生时捕获它?我只是抛出这个想法。 - Jay
@Jay:不一定。特别是在浮点数中,有一些算法类别很少发生溢出,而完全防止溢出的计算开销非常大。在性能关键的情况下,你可能更愿意使用不防止溢出的快速算法,并且对于发生溢出的那一次计算,使用谨慎、较慢的算法来避免溢出。 - Stephen Canon
@stephentyrone …我错了,谢谢。 :-) - Jay
1
如果你非常幸运,你的IEEE浮点实现可以让你设置溢出模式,这样你就可以在运行时配置溢出是否夹紧到无穷大或者引发硬件异常。例如,http://www.gnu.org/software/gsl/manual/html_node/Setting-up-your-IEEE-environment.html - Steve Jessop
这个回答解决了你的问题吗?如何检测无符号整数乘法溢出? - miken32
5个回答

6

+1. 这不仅看起来是一个好的解决方案,而且我还学到了“负溢出”和“下溢”不是同一件事... 我真傻。 - rmeador

4

在符合IEEE-754标准的系统中,默认浮点环境下,您的示例实际上不会溢出。

在这样的系统中,32位二进制浮点数的float类型,FLT_MAX在C99十六进制浮点表示法中为0x1.fffffep127。将其以十六进制整数写出来,如下所示:

0xffffff00000000000000000000000000

添加一个数(不进行四舍五入,就像这些值是任意精度整数一样),得到:

0xffffff00000000000000000000000001

但在符合 IEEE-754 标准的系统上的默认浮点数环境中,任何介于
0xfffffe80000000000000000000000000

并且

0xffffff80000000000000000000000000

(包括您指定的值) 被舍入为 FLT_MAX。不会发生溢出。

更加复杂的是,您的表达式 (FLT_MAX + 1) 可能会在编译时而不是运行时进行评估,因为它对您的程序没有可见的副作用。


3
在需要检测溢出的情况下,我使用 SafeInt<T>。它是一个跨平台的解决方案,在发生溢出时会抛出异常。
SafeInt<float> f1 = FLT_MAX;
f1 += 1; // throws

它可以在codeplex上获得


SafeInt是必备的库,那么浮点数有相应的库吗?SafeInt<float>无法编译。 - metablaster

2

早些年我在开发C++(199x)时使用过一种叫做Purify的工具。那时候,它是一种仪器化目标代码并在测试运行期间记录所有“不好”的工具。

我快速搜索了一下,但不确定它是否仍然存在。

据我所知,现在有几种开源工具可以做类似的事情。可以试试Electricfence和Valgrind。


2
Purify已经存在,现在是IBM的Rational工具集的一部分。 - Jonathan Leffler

0

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