猿问

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

似乎有大约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()。我是否缺少明显的东西?谢谢!


慕沐林林
浏览 679回答 2
2回答

繁花不似锦

在以下情况下,您可能具有未定义的行为:int nbins;不初始化nbins,因此它包含垃圾数据,可能是非常大的数字。fread(&nbins, sizeof(int), 1, fd);未经测试,因此可能会失败并保持nbins未初始化状态。了解有关fread的信息。printf("nbins = %d", nbins);有没有\n和后面没有一个明确的fflush,所以不要显示任何东西(因为stdout是通常行缓冲)。coords = malloc(nbins * sizeof(float));将要求大量的内存,所以会失败,并得到NULL在coordsfread(coords, sizeof(float), nbins, fd);NULL自UB以来写入指针,给出分段违规你很幸运。事情可能变得更糟(我们所有人都可能被黑洞摧毁)。你也可以尝试一些鼻恶魔,甚至更糟的是,有一些执行这似乎对明显的工作。下次,请避免UB。我不想消失在黑洞中,所以请忍受。顺便说一句,如果您使用GCC,请编译所有警告和调试信息:gcc -Wall -Wextra -g。它会警告您。如果没有,您将在gdb调试器下获得SEGV&nbsp;。在Linux上,valgrind和strace都可以提供帮助。请注意,无用的初始化(例如,在您的情况下为显式&nbsp;int nbins = 0;)在实践中不会有害。如果它们没有用(并且当它们不是无用的时(如您的情况,它们非常快)),则优化编译器可能会删除它们。必读拉特纳(Lattner)的博客:每个C程序员应了解的UB知识。相关概念:假设规则。另请阅读您正在使用的每个功能的文档(甚至与一样常见printf)。

猛跑小猪

由于我的问题在断言中显示为不正确,因此我将其作为正确答案(因为它指出了问题所在)。导致赛格故障的实际误差不涉及fread()对的int
随时随地看视频慕课网APP
我要回答