在C++中整数溢出陷阱的开销有多大?

2020-09-24 14:18:21

编程语言中的整数有一个有效范围,但是算术运算可能会导致值超出这样的范围。例如,将两个大整数相加可能会产生一个无法用INTEGER类型表示的整数。我们经常将这样的错误条件称为溢出。

在SWIFT这样的编程语言中,溢出将导致程序中止执行。其基本原理是,一旦算术操作失败,程序可能执行的其他所有操作都是可疑的,您最好中止该程序。大多数其他编程语言就不那么谨慎了。例如,默认情况下,在发布模式下编译的Rust程序不会中止。

在C++中,大多数编译器会简单地忽略溢出。但是,流行的编译器为您提供了选择。在使用GCC和CLANG时,可以使用-ftrapv标志指定整数溢出应该导致程序崩溃(中止)。

我对性能影响很好奇,所以我编写了一个小程序,简单地将大型数组中的所有值相加。我寻求的答案很大程度上取决于编译器的选择:

在没有陷阱的情况下,clang编译器比GCC(0.11vs.0.17)高出50%,但这不应该让我们太过关注:它是一个单一的微基准测试。

更重要的是,在GCC中启用溢出捕获会导致数量级的减慢。虽然这只是一个微基准,但结果的规模表明我们应该关注。查看程序集,我发现clang编译器在x64处理器上生成合理的代码,并在检测到溢出时添加简单的跳转。同时,GCC似乎调用了优化不佳的运行时库函数。