C - Исключение с плавающей запятой (дамп ядра)

Предполагается, что эта функция пиксель за пикселем размывает изображение, изменяя цвет каждого пикселя на среднее значение цветов вокруг него в «радиусе» 2n+1.

(Та часть, где происходит переход к следующему пикселю, уже реализована, не волнуйтесь).

Я успешно скомпилировал этот код:

void
blur_pixels(image *img, pixel *p, size_t i, size_t j)
{
  //i = current height of pixel, j = current width of pixel
  int side = 2*blurRate+1;
  int total = 0;
  int leftRight = i-blurRate;
  int upDown = j-blurRate;
  int tmpHr = 0, tmpHg = 0, tmpHb = 0;

  for(; upDown < j+blurRate; upDown++) {
    if(upDown >= 0 && upDown < img->height) {
      for(; leftRight < i+blurRate; leftRight++) {
        if(leftRight >= 0 && leftRight < img->width) {
          tmpHr += (p+leftRight)->r;
          tmpHg += (p+leftRight)->g;
          tmpHb += (p+leftRight)->b;
          total++;
        }
      }
    }
  }
  p->r=tmpHr/total;
  p->g=tmpHg/total;
  p->b=tmpHb/total;
}

Но когда я запускаю код, я получаю следующее исключение:

Floating point exception

Кто-нибудь знает, почему?


person Asfourhundred    schedule 08.05.2017    source источник
comment
Вы уверены, что total это ›0 после цикла?   -  person tkausl    schedule 08.05.2017
comment
Возможно деление на ноль. Используйте отладчик.   -  person Eugene Sh.    schedule 08.05.2017
comment
Вероятно, всего 0.   -  person Diego Romero Rodriguez    schedule 08.05.2017
comment
OT: Вы не используете upDown для настройки указателя пикселя, поэтому вы всегда будете читать одну и ту же строку (строку 0) изображения. Однако это не имеет отношения к вашей ошибке. (Кроме того, я не понимаю использования глобального вместо передачи blurRate в качестве параметра.)   -  person rici    schedule 08.05.2017


Ответы (1)


Код выполняет деление на 0 с помощью p->r=tmpHr/total;

total, вероятно, равен нулю, потому что предупреждения компилятора не включены, показывая смешанную математику со знаком и без знака цикла for(). Включите все предупреждения компилятора.

Сравнение upDown < j+blurRate и другого кода выполняется с использованием математики без знака, вероятно, не так, как ожидает OP, и внутреннее total++; никогда не происходит. Если upDown < 0, то upDown в upDown < j+blurRate становится большим беззнаковым значением. Тогда сравнение ложно.

size_t j  // an unsigned type
...
int upDown = j-blurRate;
...
for(; upDown < j+blurRate; upDown++) {  // not firing

Одним из решений было бы использование только int переменных. Более надежное решение будет использовать математику без знака, но для хорошего ответа потребуется больше кода более высокого уровня.

Что-то вроде:

blur_pixels(image *img, pixel *p, size_t i, size_t j) {
  //i = current height of pixel, j = current width of pixel
  size_t side = 2u*blurRate+1;
  size_t total = 0;
  size_t leftRight = (i > blurRate) ? i-blurRate : 0;
  size_t upDown = (j > blurRate) ? j-blurRate : 0;
  int tmpHr = 0, tmpHg = 0, tmpHb = 0;

  for(; upDown < j+blurRate; upDown++) {
    if (upDown < img->height) {
      // I suspect leftRight needs to be set here each iteration
      size_t leftRight = (i > blurRate) ? i-blurRate : 0;
      for(; leftRight < i+blurRate; leftRight++) {
        if (leftRight < img->width) {
          tmpHr += (p+leftRight)->r;
          tmpHg += (p+leftRight)->g;
          tmpHb += (p+leftRight)->b;
          total++;
        }
      }
    }
  }
  if (total) {
    p->r = tmpHr/total;
    p->g = tmpHg/total;
    p->b = tmpHb/total;
  } else {
    p->r = p->g = p->b = 0;
  }
}
person chux - Reinstate Monica    schedule 08.05.2017