There seem to be of the order of 10 questions and (mostly) successful answers solving segmentation faults cause by misused fread()'s in C. That being said, I am having such a problem but have not found a solution.
I have a binary file containing an
#define BPATH "/path/to/file"
int main(int agrc, char **argv)
num = 5;
sprintf(fname,"%s/file%d.dat", BPATH, num);
printf("Can't open file: %s\n\n",fname);
printf("Reading input file:\n");
printf("%p: %s\n", fd, fname); // prints successfully
fread(&nbins, sizeof(int), 1, fd);
printf("nbins = %d", nbins); // seg faults before this print
/* EDIT: the above print isn't properly flushed without an \n
* The seg fault was not caused by the fread(), but the lack of
* the above print lead to the confusion */
coords = malloc(nbins * sizeof(float));
fread(coords, sizeof(float), nbins, fd);
nbins = 5; // this 5 is just an example...
fwrite(nbins, sizeof(int), 1, file_ptr);
fwrite(coords, sizeof(float), nbins, file_ptr);
int *nbins = malloc(sizeof(int));
fread(nbins, sizeof(int), 1, fd);
You may have undefined behavior, with the following scenario:
int nbins; does not initialize
nbins, so it contains junk data, potentially a very large number.
fread(&nbins, sizeof(int), 1, fd); is not tested so could fail and keep
nbins uninitialized. Read about fread.
printf("nbins = %d", nbins); has no
\n and is not followed by an explicit
fflush so don't show anything (since
stdout is usually line-buffered).
coords = malloc(nbins * sizeof(float)); would request a huge amount of memory, so would fail and get
fread(coords, sizeof(float), nbins, fd); writes to the
NULL pointer, giving a segmentation violation, since UB
You are very lucky. Things could be worse (we all could be annihilated by a black hole). You could also experiment some nasal demons, or even worse, have some execution which seems to apparently work.
Next time, please avoid UB. I don't want to disappear in a black hole, so bear with us.
BTW, if you use GCC, compile with all warnings and debug info :
gcc -Wall -Wextra -g. It would have warned you. And if it did not, you'll get the SEGV under the
gdb debugger. On Linux both valgrind and strace could have helped too.
Notice that useless initialization (e.g. an explicit
int nbins = 0; in your case) don't harm in practice. The optimizing compiler is likely to remove them if they are useless (and when they are not useless, as in your case, they are very fast).
Lattner's blog: What Every C Programmer should know about UB
Read also the documentation of every function you are using (even as common as