运行时发生奇怪的崩溃

时间:2014-02-12 15:53:14

标签: c++ gcc undefined-behavior modulus

有没有人知道,为什么以下代码崩溃,用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;
}

当我删除sum + = i时;它不会崩溃。

我尝试在windows和linux linaro下使用

编译它

g ++(Ubuntu / Linaro 4.7.3-1ubuntu1)4.7.3 版权所有©2012 Free Software Foundation,Inc。 这是免费软件;查看复制条件的来源。没有 保证;甚至不适用于适销性或特定用途的适用性。

g ++(tdm-2)4.8.1 版权所有(C)2013 Free Software Foundation,Inc。 这是免费软件;查看复制条件的来源。没有 保证;甚至不适用于适销性或特定用途的适用性。

4 个答案:

答案 0 :(得分:5)

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

if(number % i == 0)

您可以在此处修复:

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

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

答案 1 :(得分:3)

你除以0是因为我在for循环中以0开始,然后你尝试得到除法的剩余部分

答案 2 :(得分:2)

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

我想知道是否删除“sum + = i”会导致某种优化,以至于因为空体而永远不会检查if条件。

答案 3 :(得分:1)

这不会在编译过程中崩溃( see it live )但你在这里有undefined behavior

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

因为i0开始,而模数为零是未定义的。这在C ++标准草案部分5.6 乘法运算符段落 4 中有所涵盖:

  

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

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