【问题标题】:Segmentation Fault by trying to access binary file [closed]尝试访问二进制文件导致分段错误[关闭]
【发布时间】:2019-05-14 18:15:07
【问题描述】:

我的程序将矩阵存储在二进制文件中,当我尝试在相同的程序使用过程中“加载”它们时,一切正常。

但是,当我关闭程序并稍后使用它时,无法访问相同的文件,并且出现分段错误(核心转储)错误。

这是“加载”矩阵的函数:

void Loading(int mat**){
  char* name = malloc(sizeof(char)*20);
  printf("Enter name of the file");
  scanf("%s",name);
  FILE* file=fopen(name,"rb");
  if (file==NULL){
    printf("error opening file");
    exit(0);
  }
  fread(mat,sizeof(int)*M*M,1,file);
  fclose(fichier);
}

其中 M 是一个常数。

当我在同一程序使用期间存储/加载多次时,它再次完美运行

对不起,我不是说英语的人

【问题讨论】:

  • 请正确缩进您的代码,使其可读。可读的代码本质上对有好处。
  • 问题很可能出在调用Loading 的代码中,而您没有显示。 Loading 看起来或多或少是正确的。顺便说一句:(int mat**) 不是 C,应该是 (int **mat) 吗?请显示真实代码。另请阅读:How to Askminimal reproducible example
  • 要回答这个问题,我们至少需要查看写入文件的代码。最好还显示在读取和写入两种情况下数组 id 是如何分配的。
  • 请复制/粘贴真实代码。
  • @ryyker:“否则,这似乎是一个写得相当好的问题”我反对,上下文丢失了。散文是不够的,还要看代码,不然就多猜了。

标签: c file segmentation-fault


【解决方案1】:

您有一个指向矩阵int **mat 的缓冲区的指针。 问题是,这并不指向内存中的单个连续位置。 int mat** 是指向 int 指针数组的指针。这是内存中的一个位置,应该包含一个接一个存储的更多指针。然后它们中的每一个 (int*) 应该指向不同的数组,最终将包含整数数组。

基本上,您使用命令 fread 将整个数据写入指针数组。也许您根本没有足够的空间来存储您的数据。即使你愿意,你也需要另一种指针。 如果你有一个连续数组,你可以使用int * 指向它。然后你会通过计算一个索引来选择一些元素。

int *mtx = (int*) malloc(M*M*sizeof(int);
int x = 2, y = 3;
int index = y*M+x;
mtx[index] = 123; // write to matrix coordinates 2,3

您可以毫无问题地将 fread 与这种缓冲区一起使用,只需检查输入文件中的矩阵元素是如何索引的,也许 x,y 被交换了。

【讨论】:

  • "Mangled arrays" 有点像恐龙。更好的版本:int (*mtx)[M] = malloc (sizeof(int[M][M])); mtx[x][y] = something;。如果 M 是一个整数常量,它甚至可以在恐龙 C 中使用。
  • @Lundin - 我不明白这条评论的一部分。 (我了解避免损坏数组内容的部分。)但是为什么您建议这个答案创建的不仅仅是一个简单的(即单维)内存区域? OP 的意图显然是读取单个连续的内存区域。
  • @ryyker 因为一维矩阵不好玩?
  • 对不起恐龙的东西。我倾向于从 OP 的角度来解决问题。如果我提出易于理解的解决方案,OP 可以立即选择解决方案并继续前进。也许他不会学到那么多。无论如何,我也在学习,同时回答问题。
  • "int mat** 是指向 int 指针数组的指针" 不幸的是不是。它是一个指向int 的指针,仅此而已。
【解决方案2】:

如前所述,该问题缺少可以进行全面分析的关键要素,也没有完整的答案。但是对于显示的内容,这里有一些建议:

1) 无法绝对确定您的分段错误的原因,因为您的帖子中缺少某些部分。然而,考虑到它有时起作用,而不是其他情况,这表明 undefined behavior 正在发挥作用。如果我要猜测未定义行为的根源,那将是您传递了一个双指针变量int **mat,而只需要一个单指针变量int *mat(参见下面fread() 的原型。),进一步让我相信mat 的内存没有被正确创建。我建议改变:

void Loading(int mat**) // double pointer is not needed here

void Loading(unsigned int mat*) //and memory allocation method adjusted accordingly.   

(请参阅下面 3 中unsigned 的原因)。)

2)函数fread()的原型是:

size_t fread (void *Buffer, size_t Element_Size, size_t Number_of_Elements, FILE *Stream);

在您的电话中:

fread(mat,sizeof(int)*M*M,1,file);

参数 2 和 3 似乎颠倒了。应该是这样写的:

fread(mat, sizeof(unsigned int), M*M, file);

3)为什么在处理二进制数据时unsigned intint 相比?:

  • 您的帖子没有明确说明数据是如何写入文件的,或者确切地说是什么格式,但通常,在处理二进制数据时,最好坚持 unsigned 类型reasons listed here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-30
    • 2018-05-01
    • 2016-10-22
    • 1970-01-01
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多