编译器是否有可能检测到整数溢出或其他数据类型溢出的可能性?

时间:2017-09-19 12:00:51

标签: c++ c error-handling warnings integer-overflow

是否可以在编译时检测或防止整数溢出而不是在运行时?

如果未检测到溢出且在运行时发生溢出,是否可以检测到?我在某处读到,如果某个操作出现溢出,处理器将设置一个特定的标志。

如何读取处理器的特定标志? 我应该问这是一个单独的问题吗?

修改

我的问题是关于签名和无符号溢出。 当我们有一个无符号变量时,它仍然会溢出并将自身设置为0或接近0的东西,对吧?或者这是我遗失的东西?

2 个答案:

答案 0 :(得分:6)

在一般情况下,无法在编译时检测和防止溢出。在特定情况下,可以在编译时检测到明显的溢出,例如在常量表达式评估期间发生的溢出,并且编译器通常会报告此类问题。

请注意,溢出是C中带符号算术的一个问题。无符号算术以超过提升类型最大值的2的幂为模。

编译器做的是假设由程序员编码执行的带符号算术不会溢出并基于此假设优化代码。例如,积极的优化器可以省略以下测试:

int test(int x) {
    if (x + 1 > x) {
        /* this is not a way to test for potential wrap-around
         * since overflow is UB, the compiler can assume that incrementing
         * an int always evaluates to a larger int.
         */
        return x + 1;
    }
    return 0;
}

在C标准中未指定在运行时检测溢出。代码生成器可以以相对较低的开销为此目的添加指令以执行特定的溢出处理。其他语言也这样做,但许多C开发人员不愿意为他们错误地认为永远不会发生的事情带来最小的开销。将此作为调试模式很有用,现代gcc和clang编译器提供 sanitize 选项以进行地址检查和其他问题。例如,您应该检查-fsanitize=undefined

对于无符号溢出,可以通过检查处理器标志的额外生成代码进行运行时检测,但由于定义了行为,因此清理选项似乎并不关心这种类型的溢出。 / p>

另一种方法可能更适合您的目的:gcc提供内置函数来执行有符号和无符号算术并在运行时报告溢出:

答案 1 :(得分:0)

仅回答问题的第二部分:

有些编译器有特殊的内置函数来检测溢出。通常它会增加大量开销,并且整数计算执行速度会比执行相同检查的C代码慢得多但速度要快。 https://gcc.gnu.org/onlinedocs/gcc-7.1.0/gcc/Integer-Overflow-Builtins.html