空闲内存用于 C 中的结构但失败(代码来自 C Primer Plus 第 6 版)

free memory used for struct in C but fails (code from C Primer Plus 6th Edition)

我 运行 来自清单 17.2,P781,C Primer Plus 第 6 版的代码。

/* films2.c -- using a linked list of structures */    
#include <stdio.h>    
#include <stdlib.h>   /* has the malloc prototype */    
#include <string.h>   /* has the strcpy prototype */    
#define TSIZE 45      /* size of array to hold title */                                                                                                                  

struct film {    
    char title[TSIZE];    
    int rating;    
    struct film *next;  /* points to next struct in list */    
};    

char *s_gets(char *st, int n);    


int main(void)    
{    
    struct film *head = NULL;    
    struct film *prev, *current;    
    char input[TSIZE];    

    /* Gather and store information */    
    puts("Enter first movie title:");    
    while (s_gets(input, TSIZE) != NULL && input[0] != '[=10=]') {    
        current = (struct film *) malloc(sizeof(struct film));    
        if (head == NULL)   /* first structure */    
            head = current;    
        else   /* subseqent structures */    
            prev->next = current;    
        current->next = NULL;    
        strcpy(current->title, input);    
        puts("Enter your rating <0-10>:");    
        scanf("%d", &current->rating);    
        while (getchar() != '\n')    
            continue;    
        puts("Enter next movie title (empty line to stop):");    
        prev = current;    
    } 

    /* show list of movies */    
    if (head == NULL)    
        printf("No data entered.");    
    else    
        printf("Here is the movie list:\n");    
    current = head;    
    while (current != NULL) {
        printf("Movie: %s     Rating: %d\n",
                current->title, current->rating);
        current = current->next;
    }

    /* Program done, so free allocated memory */
    current = head;
    while (current != NULL) {
        free(current);
        printf("Movie: %s, Rating: %d\n",                                                                                                                                
                current->title, current->rating);
        current = current->next;
    }
    printf("Bye!\n");

    return 0;
}

char *s_gets(char *st, int n)
{
    char *ret_val;
    char *find;

    ret_val = fgets(st, n, stdin);
    if (ret_val) {
        find = strchr(st, '\n');  // look for newline
        if (find)    // if the address is not NULL,
            *find = '[=10=]';    // place a null character there
        else
            while (getchar() != '\n')
                continue;      // dispose of rest of line
    }
    return ret_val;
}

我的问题是free(current)之后,current->titlecurrent->rating还在,current->next不是NULL。我不知道为什么。

至少这个循环是不正确的

current = head;
while (current != NULL) {
    free(current);
    printf("Movie: %s, Rating: %d\n",                                                                                                                                
            current->title, current->rating);
    current = current->next;
}

应该有

current = head;
while (current != NULL) {
    printf("Movie: %s, Rating: %d\n",                                                                                                                                
            current->title, current->rating);
    struct film *tmp = current;
    current = current->next;
    free(tmp);
}

否则您正在尝试使用无效的已删除指针。

变量仍然可用,但分配的 space 不是,因此您将有未定义的行为。 它现在可以工作,但稍后可能会崩溃。 一个好的做法是在释放指针后将指针设置为 NULL。

其他答案中提到的代码不正确。

在随后的一页中,作者确实展示了一个正确的链表释放函数。他说

The code saves the address of the next node because the call to free(), in principle, may make the contents of the current node (the one pointed to by *plist) no longer available.

虽然在技术上是正确的,但这段话使作者失去了 C 语言讲师的资格。这是更正后的段落。

The code saves the address of the next node because the call to free() makes the contents of the current node (the one pointed to by *plist) no longer available, and accessing it is undefined behaviour.

显然作者从来没有提到过这个词"undefined behaviour"。这在任何严肃的 C 教科书中都是不可接受的。