2014-02-12 3 views
2

Кто-нибудь знает, почему следующие коды сбой, когда он скомпилирован с 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; это не сбой.

Я попытался скомпилировать его под окнами и Linux Linaro с

г ++ (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3 Copyright © 2012 Free Software Foundation, Inc. Это свободное программное обеспечение; см. источник условий копирования. Существует NO гарантия; даже для КОММЕРЧЕСКОЙ ЦЕННОСТИ или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННОЙ ЦЕЛИ.

и

г ++ (ТДМ-2) 4.8.1 Copyright (C) 2013 Free Software Foundation, Inc. Это свободное программное обеспечение; см. источник условий копирования. Существует NO гарантия; даже для КОММЕРЧЕСКОЙ ЦЕННОСТИ или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННОЙ ЦЕЛИ.

+0

Сбой при компиляции или после запуска программы? У вас есть деление на нулевую ошибку, которая является неопределенным поведением. –

ответ

4

Это вызывает SIGFPE. Причина в том, из-за деления на ноль:

if(number % i == 0) 

Вы можете это исправить здесь:

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

SIGFPE будет происходить, как правило, в системах с точки плавучего, что вызывает исключение в этом дело. Фактическое поведение зависит от деталей импликации и не определено. В старых системах с библиотекой эмуляции с плавающей запятой он может возвращать 0 или или случайный результат.

+1

Не нужно вызывать 'SIGFPE', он не определен, все может случиться. –

3

Вы делите на 0, потому что я инициируют 0 в течение цикла, а затем вы пытаетесь получить использованную в течение разделения

+0

P.S. Я не скопировал другие ответы, они пришли в то же самое время, что и мой – ioanD

2

В первый раз через петлю, то есть я = 0. Вы не может делить на ноль, поэтому ваш «номер% i» плох. Он появляется в вашей системе, что приводит к сбою.

Интересно, что удаление «sum + = i» вызывает некоторую оптимизацию, так что условие if никогда не проверяется из-за пустого тела.

+0

интересное представление об оптимизации ... Другие ответы не обратили внимание на эту деталь. – user2018675

+0

Ну, bevahiour не определено, так что все может случиться. – Devolus

1

Это не врезаться во время компиляции (see it live), но у вас есть undefined behavior здесь:

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

С i начинается в 0 и модуля на ноль не определен. Это рассматривается в проекте C++ стандартной секции 5.6мультипликативные операторы пункт :.

[...] Если второй операнд/или% равно нулю поведение не определено [...]

Это означает, что что-то может случиться, что включает в аварию и в самом деле, если я использую -O3 флаг он больше не падает на Coliru (see it live). Это также вполне приемлемое неопределенное поведение.