似乎有10个问题的顺序和(大多数)成功的答案解决因C中误用的fread()导致的分段错误。那么说,我遇到了这样的问题但是没有找到一个办法。
我有一个二进制文件,其中包含int
(称之为 nbins )和一个float
的数组(大小为 nbins )。当我尝试读取此文件时,它会成功打开并指向文件句柄,但在阅读 nbins int
时会出现分段错误错误。这是一个最小的例子:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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()
来读它。我错过了一些明显的东西吗谢谢!
答案 0 :(得分:4)
您可能拥有undefined behavior,具体情况如下:
int nbins;
未初始化nbins
,因此它包含垃圾数据,可能是一个非常大的数据。
fread(&nbins, sizeof(int), 1, fd);
未经过测试,因此可能会失败并保持nbins
未初始化。阅读fread。
printf("nbins = %d", nbins);
没有\n
,后面没有明确的fflush
,因此不要显示任何内容(因为stdout
通常是 行缓冲)。
coords = malloc(nbins * sizeof(float));
会请求大量内存,因此会失败并在NULL
中获得coords
fread(coords, sizeof(float), nbins, fd);
写入NULL
指针,导致分段违规,因为UB
你很幸运。事情可能是worse(我们都可能被一个黑洞消灭)。你也可以尝试一些nasal demons,或者更糟糕的是,有一些似乎的执行显然有效。
下次请避免 UB 。我不想在黑洞中消失,所以请耐心等待。
BTW,如果您使用GCC,请编译所有警告和调试信息:gcc -Wall -Wextra -g
。它会警告你。如果没有,您将在gdb
调试器下获得SEGV。在Linux上,valgrind和strace也可以提供帮助。
请注意,无用的初始化(例如您的显式 int nbins = 0;
)在实践中不会造成伤害。优化编译器可能会删除它们,如果它们没用(当它们没用时,就像你的情况一样,它们非常快)。
Lattner的博客:What Every C Programmer should know about UB。相关概念:As-if rule。
另请阅读您正在使用的每个功能的文档(即使与printf
一样常见)。