【问题标题】:C, gets() can be dangerous. Data from file won't appear [duplicate]C,gets() 可能很危险。文件中的数据不会出现[重复]
【发布时间】:2018-12-10 05:44:23
【问题描述】:

当我尝试运行此代码时,我得到的只是一个警告,即 gets() 太危险,无法使用。然后当我运行它时,我会变得空白。我想显示这个:

Ollie     2.9   freshmen
John      3.2   senior  
Julie     2.2   freshmen
Joe       1.8   freshmen
Mary      3.8   senior  
Sue       3.4   junior  
Jane      2.7   senior  
Bob       2.8   senior  
Fred      3.2   freshmen
Bill      3.3   junior  

这是我的代码:

Student *top = NULL; // to point top node of list
Student * temp, *temp1, *temp2; // for traversing list

// Creates the entire linked list from the file.
// Should call readNext and push
// Returns head of the linked list
Student *buildStudentList()
{
    Student *p; // will hold the data to be pushed in list
    p = readNext();
    push(&top, p);
    return top; //TODO: Change return
}

//Read a single line from standard input and return a student structure located on the heap
Student *readNext()
{
    Student *s = (Student*)malloc(sizeof(Student)); // allocating dynamic memory in heap
    printf("Please Enter Student Name, gpa, year :");
    gets(s->name);
    scanf("%f", &s->gpa);
    gets(s->year);
    s->next = NULL; // initially make next as NULL
    return s; //TODO: Change return
}

//Return a student structure stored on the heap
Student *makeStudent(char *name, float gpa, char *year)
{
    Student *s = (Student*)malloc(sizeof(Student));// allocating memory in heap
    s->name = name;
    s->gpa = gpa;
    s->year = year;
    s->next = NULL;
    return s; //TODO: Change return
}

//insert a new student node at the head of the linked list
void push(Student **list, Student *student)
{
    top = *list;
    student->next = top; // assign current top node of list to be second node of the list
    top = student; // make current node as top node of the list
    printf("push successful.\n");
}

//Insert a student node in the desired position on the linked list
void insert(Student *list, Student *s, int position)
{
    int i;
    top = list;
    temp = top;// temp is for traversing the list
    for (i = 1; i < position - 1; i++) // loop to reach desired position in the list
    {
        temp = temp->next;
    }
    if (temp == NULL)
    {
        printf("Position does not exist.\n");
    }
    else
    {
        s->next = temp->next;
        temp->next = s;
    }
}

//Displays contents of a single student structure
void display(Student *s) {
    printf("NAME:%s\t| GPA:%f\t| YEAR:%s\n", s->name, s->gpa, s->year);
}

//Displays contents of the entire linked list
void displayAll(Student *list)
{
    temp = list;
    while (temp != NULL)
    {
        display(temp);
        temp = temp->next;
    }
}

//Delete all data allocated on the heap before terminating program
void cleanUp(Student *list)
{
    temp1 = list; // will point to the top node of list
    temp2 = temp1->next; // will point to the second node of the list
    while (temp1 != NULL)
    {
        free(temp1);
        temp1 = temp2;
        temp2 = temp2->next;
    }
    printf("Cleanup Successful.\n");
}

//Main function tests your functions.
int main()
{
    Student *list, *s;
    printf("Program Started ");

    //Construct Linked List from Standard Input
    list = buildStudentList();

    //Insert a new student in desired position
    s = makeStudent("Max", 3.0, "senior");
    insert(list, s, 1);

    //Display entire linked list
    displayAll(list);

    //Free all heap memory
    cleanUp(list);
    printf("Program Successful Exit ");

    return 0;
    //exit(EXIT_SUCCESS);
}

这是我得到的输出:

Program Started
Segmentation fault

我应该尝试使用 fgets() 而不是 gets() 吗?我试图做的输出是不同文件的一部分,这对它有影响吗?

【问题讨论】:

  • 这段代码确实很危险。您正在将字符串读入未初始化的指针。 fgets 不会帮你解决这个问题。
  • 你不应该使用gets,句号。但你的问题在别处。
  • 您在第一条评论中被告知您有未初始化的指针。这才是真正的问题。
  • 请不要每隔一行使用换行符。并缩进你的代码。
  • 你能展示Student结构的声明吗? nameyear 是如何定义的?

标签: c pointers struct malloc


【解决方案1】:

忽略警告绝不是正确的做法。目的不仅仅是使用一些技巧来消除警告,而是解决产生警告的根本原因。在这种特殊情况下,编译器明确警告您使用gets 太危险了。为什么你不听这样一个明确的警告?

gets 从 C11 开始已从标准中删除。

gets() 函数不执行边界检查,因此该函数极易受到缓冲区溢出攻击。它不能安全使用(除非程序在限制stdin 上出现的内容的环境中运行)。出于这个原因,该功能在 C99 标准的第三次勘误中已被弃用,并在 C11 标准中完全删除。 fgets()gets_s() 是推荐的替代品。

永远不要使用gets()

还要查看结构成员的内存分配/释放。

也可以在whether the result of malloc should be cast阅读这个问题。

【讨论】:

    【解决方案2】:

    你好,我浏览了你的代码,假设你的结构描述如下:

    typedef struct Student_s{
        char name[32];
        float gpa;
        char year[5];
        struct Student_s* next;
    }Student;
    

    gets() 的问题已经在P.W 之前的回答中指出 .你可以用scanf("%s",s-&gt;name)代替gets()

    makeStudent() 中,您应该使用strcpy() 来复制字符串。 [Reason]

    同样在cleanUp() 中考虑释放最后一个节点的情况,temp1 将指向最后一个节点,temp2 指向NULL。在这种情况下,如果您执行temp2 = temp2-&gt;next,它将导致segmentation fault。您可以通过将语句括在 if 中来避免这种情况。

    if(temp2 != NULL){
        temp2 = temp2->next;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-07-20
      • 2011-02-20
      • 2017-09-30
      • 1970-01-01
      • 2016-02-17
      • 2014-11-29
      • 1970-01-01
      • 2021-08-24
      • 2011-06-21
      相关资源
      最近更新 更多