由函数中的malloc和sscanf引起的seg错误

时间:2010-05-26 16:13:02

标签: c arrays pointers malloc segmentation-fault

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

当我在main函数中有所有内容时(参见示例1),但是当我将它转移到第二个函数时(见下面的示例2),它不起作用。在示例2中,当我在sscanf (line,"%i",classes[i]);正确解释gdb时出现seg错误。

我害怕,这可能是微不足道的,但有一天我已经浪费了。

提前致谢。

[示例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
...

2 个答案:

答案 0 :(得分:2)

此:

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

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

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

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

您也可以使用

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

这可能更清楚,取决于你对这些东西的舒适度。

答案 1 :(得分:0)

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

int*& classes instead of int** classes

然后你可以使用与主函数相同的代码。