-1

I'm facing a problem when trying to read a binary file of fixed size. The code below returns segmentation Fault just before closing the file. What I want to achieve it is to return an int pointer back to the main function.

The file it s a raw grayscale image, which has values from 0 to 255, that's why I'm using unsigned char.

How can I convert and assign from unsigned char to *int properly?

Any kind of help will be welcome!

void readBinaryFile(char *filename, int *in){

    FILE *file;
    long length;
    unsigned char *imagen;

    int c;

    file = fopen(filename, "rb");
    fseek(file,0,SEEK_END);
    length = ftell(file);

    imagen = (unsigned char *) malloc(length);
    fseek(file, 0, SEEK_SET);
    fread(imagen, length,  1 , file);

    int cont;
    //c+4: file contains values from 0 to 255 
    for(c=0,cont=0;c<length;c=c+4,cont++){
       in[cont] = (unsigned char) imagen[c];         
    }


    for(cont=0;cont<length/4;cont++){
       printf("%d",(int) in[cont]);
    }

    fclose(archivo);
    free(imagen_buffer);
}

void main(int argc, char **argv){

    int *in;           
    int fixed_size = 784;
    in = (int *) malloc((fixed_size)*(fixed_size));
    readBinaryFile("test.raw", in);

    int c;

    for(c=0;c<((fixed_size)*(fixed_size));c++){
        printf("%d", (unsigned char) in[c]);
    }           
}
alk
  • 69,737
  • 10
  • 105
  • 255
Charles
  • 31
  • 3

1 Answers1

2

This

int *in;

makes in point to an int.

This

 in = (int *) malloc((fixed_size)*(fixed_size));

allocates to in 784*784=614656 bytes.

  1. You need 784*784 ints.
  2. An int needs sizeof (int) bytes, which by definition is very well might be and most often is larger then 1.

From 1. and 2. above it can be deduces that 784*784 int needs more then 784*784 bytes.

So change

in = (int *) malloc((fixed_size)*(fixed_size));

to be

in = (int *) malloc((fixed_size)*(fixed_size) * sizeof (int));

or even nicer and safer with less noise do

in = malloc(fixed_size*fixed_size * sizeof *in);

because

  • in C there is no need to cast void* (which malloc() returns).
  • the parentheses around fixed_size are useless.
  • using sizeof *in returns the same as sizeof (int), but would "survive" if you changed int * in to become for example unsigned * in.

Also while reading you need to make sure to not read more then 784*784 char, as else the memory allocated for the int will be overflowed, which in turn invoked the infamous Undefined Behaviour.

alk
  • 69,737
  • 10
  • 105
  • 255
  • dude, I was stuck in this like all night, THANKS ! – Charles Sep 23 '18 at 10:02
  • The size of `int` is not more than one by definition. It would have to be a derived property, as there is no such definition. However, by extensive discussion elsewhere on Stack Overflow, it may be possible for a conforming implementation to have `int` and `char` be the same size. (`EOF` is a troublesome issue for that.) – Eric Postpischil Sep 23 '18 at 11:47
  • @EricPostpischil "*possible ... to have `int` and `char` be the same size*" Really? I memorise the C Standard defining `CHAR_MAX` to be 127 or 255 as maximum and `INT_MAX` to be 32767 as minimum. Mind sharing the link to the discussion you mention? – alk Sep 23 '18 at 13:06
  • @alk: The standard does not limit `CHAR_MAX` to being 127 or 255. There is discussion in [this question](https://stackoverflow.com/questions/3860943/can-sizeofint-ever-be-1-on-a-hosted-implementation). – Eric Postpischil Sep 23 '18 at 13:25
  • @EricPostpischil Oh, yes I see: Only the minimum values are defined by the Standard. My bad. Thank you for the correction. – alk Sep 23 '18 at 13:31