【问题标题】:seg fault caused by malloc and sscanf in a function由函数中的 malloc 和 sscanf 引起的 seg 错误
【发布时间】:2010-05-26 16:13:01
【问题描述】:

我想打开一个文本文件(见下文),读取每一行中的第一个 int 并将其存储在一个数组中,但我遇到了分段错误。我摆脱了所有 gcc 警告,阅读了我在网上找到的几个教程,并在 stackoverflow 中搜索了解决方案,但我无法弄清楚我做错了什么。

当我在主函数中拥有所有内容时它可以工作(参见示例 1),但当我将其转移到第二个函数时(参见下面的示例 2)就不行了。在示例 2 中,当我正确解释 gdb 时,sscanf (line,"%i",classes[i]); 出现段错误。

恐怕,这可能是一件微不足道的事情,但我已经浪费了一天的时间。

提前致谢。

[示例 1] 即使它适用于 main 中的所有内容:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

const int LENGTH = 1024;

int main() {
  char *filename="somedatafile.txt";
  int *classes;
  int lines;      
  FILE *pfile = NULL; 
  char line[LENGTH];
  pfile=fopen(filename,"r");
  int numlines=0;
  char *p;

  while(fgets(line,LENGTH,pfile)){
    numlines++;
  }

  rewind(pfile);

  classes=(int *)malloc(numlines*sizeof(int));
  if(classes == NULL){
    printf("\nMemory error.");
    exit(1);
  }
  int i=0;
  while(fgets(line,LENGTH,pfile)){
    printf("\n");
    p = strtok (line," ");
    p = strtok (NULL, ", ");
    sscanf (line,"%i",&classes[i]);
    i++;
  }
  fclose(pfile);
  return 1;
}

[示例 2] 这没有将功能转移到函数中:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

const int LENGTH = 1024;

void read_data(int **classes,int *lines, char *filename){
  FILE *pfile = NULL; 
  char line[LENGTH];
  pfile=fopen(filename,"r");
  int numlines=0;
  char *p;

  while(fgets(line,LENGTH,pfile)){
    numlines++;
  }

  rewind(pfile);

  * classes=(int *)malloc(numlines*sizeof(int));
  if(*classes == NULL){
    printf("\nMemory error.");
    exit(1);
  }
  int i=0;
  while(fgets(line,LENGTH,pfile)){
    printf("\n");
    p = strtok (line," ");
    p = strtok (NULL, ", ");
    sscanf (line,"%i",classes[i]);
    i++;
  }
  fclose(pfile);
  *lines=numlines;
}  

int main() {
  char *filename="somedatafile.txt";
  int *classes;
  int lines;

  read_data(&classes, &lines,filename) ;
  for(int i=0;i<lines;i++){
    printf("\nclasses[i]=%i",classes[i]);
  }
  return 1;
}

[somedatafile.txt 的内容]

50 21 77 0 28 0 27 48 22 2
55 0 92 0 0 26 36 92 56 4
53 0 82 0 52 -5 29 30 2 1
37 0 76 0 28 18 40 48 8 1
37 0 79 0 34 -26 43 46 2 1
85 0 88 -4 6 1 3 83 80 5
56 0 81 0 -4 11 25 86 62 4
55 -1 95 -3 54 -4 40 41 2 1
53 8 77 0 28 0 23 48 24 4
37 0 101 -7 28 0 64 73 8 1
...

【问题讨论】:

    标签: c arrays pointers malloc segmentation-fault


    【解决方案1】:

    这个:

     sscanf (line,"%i",classes[i]);
    

    可能是错误的。您也需要在那里取消引用,尝试:

     sscanf (line,"%i", &(*classes)[i]);
    

    这是因为classes 是一个指向整数数组的指针。您需要其中一个整数的地址,以便sscanf() 可以在那里写入解析后的数字。因此,您必须先取消引用classes 才能得到数组,然后说您想要该数组中元素号i 的地址。

    你也可以使用

     sscanf (line,"%i", *classes + i);
    

    这可能更清楚,这取决于您对这些事情的适应程度。

    【讨论】:

    • 谢谢,速度很快!但我以前从未见过 &(*foo)[bar] 。看起来应该和 foo[bar] 一样,但显然不是。这是什么意思?
    • classes[i] 是一个int *(*classes) 也是一个int *(*classes)[i] 是一个int&amp;(*classes)[i] 是那个int 的地址。
    【解决方案2】:

    问题是您将 [] 运算符应用于第一种情况下的 int* 和第二种情况下的 int** 。 int** 就像一个二维数组,当您将 [] 运算符与 int** 结合使用时,您将索引到一个 int* 数组。在你的情况下,这不是你想要的,因为你只初始化了这个数组中的第一个条目。因此,当您访问 classes[1] 时,它会因为未初始化而崩溃。您可以通过将指针作为引用而不是双指针传递来避免这种混淆:

    int*& classes instead of int** classes
    

    然后您可以使用与 main 函数中相同的代码。

    【讨论】:

      猜你喜欢
      • 2019-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-04
      • 1970-01-01
      • 2020-09-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多