C,gets()可能很危险。来自文件的数据不会出现

时间:2018-12-10 05:44:24

标签: c pointers struct malloc

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

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()吗?我尝试执行的输出是另一个文件的一部分,对它有影响吗?

2 个答案:

答案 0 :(得分:3)

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

从C11开始,

gets已从标准中删除。

  

gets()函数不执行边界检查,因此此函数极易受到缓冲区溢出攻击。它不能安全使用(除非程序在限制stdin上显示内容的环境中运行)。因此,该功能在第三更正版中已不支持C99标准,而在C11标准中已完全删除。建议使用fgets()gets_s()

     

请勿使用gets()

还要查看您对结构成员的内存分配/取消分配。

也请在whether the result of malloc should be cast上阅读此问题。

答案 1 :(得分:0)

您好,假设您的结构描述如下,请仔细阅读您的代码:

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

P.W在先前的回答中已经指出了gets()的问题 。您可以使用scanf("%s",s->name)代替gets()

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

还要在cleanUp()中考虑释放最后一个节点的情况,temp1指向最后一个节点,而temp2指向NULL。在这种情况下,如果您执行temp2 = temp2->next,则会得到segmentation fault。您可以通过将语句放在if中来避免这种情况。

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