Search code examples
cgccstructvalgrinddynamic-memory-allocation

Valgrind: Invalid read of size 8, bytes after a block of size 8 alloc'd


Have been looking for a simple case as I have on Stack overflow and other sites but still have not found anything, error happens on line 57, then also on line 47, valgrind saying I write a pointer which leads to an array of structures pixel, I tried to see, is there a problem with allocating memory, but it seems there is a problem with assignment bmp_file->data = file_data

==1811== error calling PR_SET_PTRACER, vgdb might block
==1811== Invalid write of size 8
==1811==    at 0x10BC02: read_bmp (bmp.c:65)
==1811==    by 0x1092D7: main (main.c:12)
==1811==  Address 0x4b97268 is 0 bytes after a block of size 8 alloc'd
==1811==    at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1811==    by 0x10BB88: read_bmp (bmp.c:52)
==1811==    by 0x1092D7: main (main.c:12)
==1811== 
==1811== Invalid read of size 8
==1811==    at 0x10BC16: read_bmp (bmp.c:67)
==1811==    by 0x1092D7: main (main.c:12)
==1811==  Address 0x4b97268 is 0 bytes after a block of size 8 alloc'd
==1811==    at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1811==    by 0x10BB88: read_bmp (bmp.c:52)
==1811==    by 0x1092D7: main (main.c:12)
struct bmp_image* read_bmp(FILE* stream) {
  struct bmp_image* bmp_file = (struct bmp_image*)calloc(1, sizeof(struct bmp_image*));
  struct bmp_header* header = read_bmp_header(stream);

  if (header->type != 0x4d42) {
    printf("Error: This is not a BMP file.\n");
    free(bmp_file);
    free(header);
    return NULL;
  }

  struct pixel* file_data = read_data(stream, header);

  bmp_file->header = header;
  bmp_file->data = file_data;

  if (bmp_file->header == NULL || bmp_file->data == NULL) {
    printf("Error: Corrupted BMP file.\n");

    if (bmp_file->header == NULL) {
      free(bmp_file->header);
    }

    if (bmp_file->data == NULL) {
      free(bmp_file->data);
    }

    free(bmp_file);
    return NULL;
  }

  return bmp_file;
}
struct pixel* read_data(FILE* stream, const struct bmp_header* header) {
  struct pixel* data = (struct pixel*)calloc(header->height * header->width, sizeof(struct pixel));

  if (!data) {
    free(data);
    return NULL;
  }

  fseek(stream, header->offset, SEEK_SET);
  unsigned short padding = header->width % 4;

  for (int pixelIdx = 0; pixelIdx < header->height * header->width; pixelIdx++) {
    data[pixelIdx].blue = (uint8_t)fgetc(stream);
    data[pixelIdx].green = (uint8_t)fgetc(stream);
    data[pixelIdx].red = (uint8_t)fgetc(stream);

    if ((pixelIdx + 1) % (int)header->width != 0 || padding == 0) continue;

    for (int i = 0; i < padding; i++) {
      fgetc(stream);
    }
  }

  return data;
}
void free_bmp_image(struct bmp_image* image) {
  if (image == NULL) return;

  free(image->header);
  free(image->data);
  free(image);
}

Solution

  • At least this memory allocation

    struct bmp_image* bmp_file = (struct bmp_image *)calloc(1, sizeof(struct bmp_image *));
    

    is incorrect. It seems you mean

    struct bmp_image* bmp_file = (struct bmp_image *)calloc(1, sizeof(struct bmp_image));
    

    or

    struct bmp_image* bmp_file = (struct bmp_image *)calloc(1, sizeof( *bmp_file));