有没有人知道,为什么以下代码崩溃,用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。 这是免费软件;查看复制条件的来源。没有 保证;甚至不适用于适销性或特定用途的适用性。
答案 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) {
^^^
因为i
从0
开始,而模数为零是未定义的。这在C ++标准草案部分5.6
乘法运算符段落 4 中有所涵盖:
[...]如果/或%的第二个操作数为零,则行为未定义。[...]
这意味着任何事情都可能发生,包括崩溃,事实上如果我使用-O3
标志,它就不会再崩溃 Coliru ( see it live )。这也是完全可以接受的未定义行为。