为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C
慕沐林林 2019-09-27 16:07:01
似乎有大约10个问题,并且(大多数)成功解决了由于C语言中fread()使用不当而导致的分段错误的答案。话虽如此,我遇到了这样的问题,但没有找到解决方案。我有一个二进制文件,其中包含一个int(称为nbins)和一个floats(大小为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()。我是否缺少明显的东西?谢谢!
查看完整描述

2 回答

?
繁花不似锦

TA贡献1851条经验 获得超4个赞

在以下情况下,您可能具有未定义的行为

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

  • fread(&nbins, sizeof(int), 1, fd);未经测试,因此可能会失败并保持nbins未初始化状态。了解有关fread的信息。

  • printf("nbins = %d", nbins);有没有\n和后面没有一个明确的fflush,所以不要显示任何东西(因为stdout通常行缓冲)。

  • coords = malloc(nbins * sizeof(float));将要求大量的内存,所以会失败,并得到NULLcoords

  • 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知识。相关概念:假设规则。

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


查看完整回答
反对 回复 2019-09-27
?
猛跑小猪

TA贡献1858条经验 获得超8个赞

由于我的问题在断言中显示为不正确,因此我将其作为正确答案(因为它指出了问题所在)。导致赛格故障的实际误差不涉及fread()对的int

查看完整回答
反对 回复 2019-09-27
  • 2 回答
  • 0 关注
  • 678 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信