Search code examples
cpointerspixelcyclefloating-point-exceptions

C - Floating Point Exception (core dumped)


This function is supposed to, pixel by pixel, blur the image by turning the color of each pixel on the mean of the colors around it in a 2n+1 "radius".

(The part where it skips to the next pixel is already implemented, don't worry).

I successfully compiled this code:

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;
}

But when I run the code I get the following exception:

Floating point exception

Does anyone know why?


Solution

  • Code is preforming division by 0 with p->r=tmpHr/total;

    total is likely zero because compiler warnings are not turned on showing the mixed signed/unsigned math of the for() loop. Turn on all compiler warnings.

    The compare upDown < j+blurRate and other code is done using unsigned math, likely not as OP expects and the inner total++; never happens. If upDown < 0, then upDown in upDown < j+blurRate becomes a large unsigned value. Then compare is false.

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

    One solution would be to use only int variables. A more robust solution would use unsigned math, yet more of the higher level code would be needed for a good answer.

    Something like:

    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;
      }
    }