运行时奇怪的崩溃

Strange crash at runtime

本文关键字:崩溃 运行时      更新时间:2023-10-16

>有谁知道,为什么下面的代码在使用 G++ 编译时崩溃?

#include <iostream>
unsigned long getSumDivisors(const unsigned long number) {
    unsigned long sum = 0;
    for(unsigned long i = 0; i < number; ++ i) {
        if(number % i == 0) {
            sum += i;
        }
    }
    return sum;
}
int main() {
    std::cout << getSumDivisors(5);
    return 0;
}

当我删除总和 += i; 它不会崩溃。

我试图在Windows和linux linaro下编译它

g++ (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3版权所有 © 2012 自由软件基金会。这是免费软件;有关复制条件,请参阅源。 没有保证;甚至不是为了适销性或适合特定目的。

G++ (TDM-2) 4.8.1版权所有 (C) 2013 自由软件基金会。这是免费软件;有关复制条件,请参阅源。 没有保证;甚至不是为了适销性或适合特定目的。

它会导致SIGFPE。原因是因为除以零:

if(number % i == 0)

您可以在此处修复它:

 for(unsigned long i = 1; i < number; ++ i)

SIGFPE 通常发生在具有浮点单元的系统上,在这种情况下会引发异常。实际行为取决于实施细节,并且没有定义。在具有浮点仿真库的旧系统上,它可能返回 0 或随机结果。

你除以 0,因为我在 for 循环中以 0 启动,然后你尝试得到除法

> 第一次通过循环时,你有 i = 0。你不能除以零,所以你的"数字% i"是不好的。它出现在您的系统上,导致崩溃。

我想知道删除"sum += i"是否会导致某种优化,使得由于空体而永远不会检查 if 条件。

这不会在编译过程中崩溃(实时查看),但您在此处确实有未定义的行为:

if(number % i == 0) {
          ^^^

由于i0 开始,并且模数为零是不确定的。这在C++草案标准部分5.6法运算符4段中有所涉及:

[...]如果/或 % 的第二个操作数为零,则行为未定义。[...]

这意味着任何事情都可能发生,包括崩溃,事实上,如果我使用 -O3 标志,它不再在 Coliru 上崩溃(现场观看)。这也是完全可以接受的未定义行为。