1

我正在用 c 编写一个程序,该程序通过“string int”行查看标准输入的文本文件。我最初使用 scanf 使程序运行良好,但现在名称必须是动态字符串(在运行时已知大小),当我将grade_entry 中的名称切换为指针时,它开始出现分段错误

typedef struct grade_entry {
       char *name;
       int grade;
} grade_entry;

struct grade_entry grade_list[100];

int main(){
    int grade;
    int done;
    int i=0;
    do{
            puts("not weee\n");
            done=(int)strlen(gets(grade_list[i].name));
            puts("weee\n");
    }while(1);
}

编译和当前输出是:

not weee

segmentation fault(core dumped)

**已解决:我分配了指针,然后为 size+1 重新分配,将 null 添加到末尾。不幸的是,我不能根据 scanf、fgets、gets 的临时内存立即进行 malloc。哦,好的,谢谢大家的帮助

4

4 回答 4

4

您必须为 分配内存grade_entry.name,否则它是一个指向任意内存位置的 char 指针,写入它会导致分段错误。

于 2012-12-18T06:29:55.713 回答
1

你不应该使用gets()- 永远。假装不存在。假装如果你使用它会炸毁你的电脑。假设它将用于使您的程序崩溃——因为它会。

问题是您无法确定gets()它需要使用多少空间。

改为使用fgets()。如果您担心读取的行太长,那么您应该希望您的系统具有 POSIX 2008 功能getline(),它可以为您处理任意长度的读取行。您只需要处理字符指针数组,这更简单。

在您的程序中,指针最终将被复制到数据结构中的指针。

这一切都很干净有趣;关键是要记住,如果你没有初始化指针,它会随机指向,在你知道指针指向什么之前,你不能安全地使用指针。因此,初始化您的指针以指向某处,或者初始化为 NULL 以指示它们不指向任何地方。永远不要取消引用 NULL 指针。

于 2012-12-18T06:54:14.727 回答
1

您尚未为 char* 名称字段分配内存,而是将值存储在此内存中,而您实际上并不拥有该内存。

除此之外,您正在运行一个无限循环并使用相同的数组元素(不增加“i”)

以下是我猜可以工作的代码。

typedef struct grade_entry {
   char *name;
   int grade;
} grade_entry;

int main(){
int grade;
int done;
char str[100];
grade_entry grade_list[10];
int i=0;    
do{
        puts("not weee\n");
        gets(str);
        grade_list[i].name=(char*)malloc(strlen(str));
        done=strlen(grade_list[i++].name);
        puts("weee\n");
  }while(i<10);
}
于 2012-12-18T06:37:04.140 回答
1

问题出在这里:

        done=(int)strlen(gets(grade_list[i].name));//Storing in a unallocated memory using an uninitialized pointer. BAD!

除了在您的代码中,我看不到您增加/减少/更改 的值,所以基本上每次循环执行i时您都会覆盖。grade_list[0].name那也很糟糕。内存泄漏太多!!

它是一个没有中断条件的无限循环!

尝试这样的事情:

char buffer[MAX_LENGTH_OF_A_STRING];
memset(buffer,0x00,MAX_LENGTH_OF_A_STRING);
do{
        puts("not weee\n");
        done=strlen(gets(buffer));//This is enough
        grade_list[i].name=malloc(strlen(buffer)+1);
        strncpy(grade_list[i].name,buffer,strlen(buffer)+1);
        memset(buffer,0x00,MAX_LENGTH_OF_A_STRING);
        i++;//You were not doing this
        puts("weee\n");
        //Put some condition to break this infinite loop, somewhere within the loop
}while(1);
于 2012-12-18T06:40:24.907 回答