存储在二进制文件中的int不成功fread(),分段错误

似乎有10个问题的顺序和(大多数)成功的答案解决因C中误用的fread()导致的分段错误。尽管如此,我遇到了这样的问题,但还没有找到解决方案。

我有一个二进制文件,包含一个int (称为nbins )和一个float数组(大小为nbins )。 当我尝试读取此文件时,它会成功打开并指向文件句柄,但在读取nbins int时会出现分段错误错误。 这是一个最小的例子:

 #include  #include  #include  #define BPATH "/path/to/file" int main(int agrc, char **argv) { FILE *fd; int num; char fname[500]={}; int nbins; float *coords; num = 5; sprintf(fname,"%s/file%d.dat", BPATH, num); if(!(fd=fopen(fname,"rb"))) { printf("Can't open file: %s\n\n",fname); exit(0); } 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); fclose(fd); free(coords); return(0); } 

该文件是使用以下格式创建的:

 int nbins[1]; nbins[0] = 5; // this 5 is just an example... fwrite(nbins, sizeof(int), 1, file_ptr); fwrite(coords, sizeof(float), nbins[0], file_ptr); 

我也尝试过使用:

 int *nbins = malloc(sizeof(int)); fread(nbins, sizeof(int), 1, fd); 

但这并没有解决问题。 该文件确实存在且可读; 我可以使用Python读取它,使用NumPy的fromfile() 。 我错过了一些明显的东西吗 谢谢!

您可能有未定义的行为 ,具有以下方案:

  • int nbins; 不初始化nbins ,因此它包含垃圾数据,可能是一个非常大的数字。

  • fread(&nbins, sizeof(int), 1, fd); 没有经过测试,所以可能会失败,并保持nbins未初始化。 阅读有关恐惧的内容 。

  • printf("nbins = %d", nbins); 没有\n并且没有显式的fflush所以不要显示任何东西(因为stdout 通常是行缓冲的)。

  • coords = malloc(nbins * sizeof(float)); 会请求大量内存,因此会失败并在coords获取NULL

  • fread(coords, sizeof(float), nbins, fd); 写入NULL指针,因为UB而导致分段违规

你很幸运。 情况可能更糟 (我们都可能被黑洞消灭)。 你也可以尝试一些鼻子恶魔 ,或者更糟糕的是,有一些似乎显然有效的执行。

下次, 请避免UB 。 我不想在黑洞中消失,所以请耐心等待。

顺便说一下,如果您使用GCC ,请编译所有警告和调试信息: gcc -Wall -Wextra -g 。 它会警告你。 如果没有,你将获得gdb调试器下的SEGV。 在Linux上, valgrind和strace也可以提供帮助。

请注意,无用的初始化(例如, 显式的 int nbins = 0;在您的情况下)在实践中不会造成伤害。 优化编译器可能会删除它们,如果它们没用(当它们没用时,就像你的情况一样,它们非常快)。

强制阅读

Lattner的博客: 每个C程序员应该了解UB

另请阅读您正在使用的每个function的文档(甚至与printf一样常见)。