为什么这个C程序会释放不存在的内存并且不输出所写的Bye?

问题描述 投票:0回答:1

代码如下: 出自《C Primer Plus》第六版_中文版

// This program creates a linked list of films and displays them.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TSIZE 45

struct film{
    char title[TSIZE];
    int rating;
    struct film *next;
};

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

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

    printf("Enter first movie title (or enter to quit): ");
    while(s_gets(input, TSIZE)!= NULL && input[0]!= '\0')
    {
        current = (struct film*) malloc(sizeof(struct film));
        if (head == NULL)
            head = current;
        else
            prev->next = current;
        current->next = NULL;
        strcpy(current->title, input);
        printf("Enter your rating <0-10>: ");
        scanf("%d", &current->rating);
        while (getchar()!='\n')
            continue;
        printf("Enter next movie title (or enter to quit): ");
        prev=current;
    }
    if (head == NULL)
        printf("No data entered. ");
    else
        printf("Here is the list of films: \n");
    current = head;
    while (current!= NULL)
    {
        printf("Movie: %s, Rating: %d\n",
               current->title, current->rating);
        current = current->next;
    }
    current = head;
    while (current!= NULL)
    {
        printf("freeing memory for %s\n", current->title);
        current=head;
        head=head->next;
        free(current);
    }
    fflush(stdout);
    printf("Bye!\n");
    fflush(stdout);
    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');
        if (find) {
            *find = '\0';
        } else {
            while (getchar()!= '\n')
                continue;
        }
    }
    return ret_val;
}

这是运行程序的输出:

PS C:\Develop\c\c> gcc .\film2.c -o .\film2     
PS C:\Develop\c\c> .\film2     
PS C:\Develop\c\c> gcc .\film2.c -o film2  
Enter first movie title (or enter to quit): ashah
Enter your rating <0-10>: 4
Enter next movie title (or enter to quit): dhaah
Enter your rating <0-10>: 2
Enter next movie title (or enter to quit): adhazb
Enter your rating <0-10>: 1
Enter next movie title (or enter to quit):
Here is the list of films:
Movie: ashah, Rating: 4
Movie: dhaah, Rating: 2
Movie: adhazb, Rating: 1
PS C:\Develop\c\c> .\film2.exe
Enter first movie title (or enter to quit): SG
Enter your rating <0-10>: 32
Enter next movie title (or enter to quit): aghah
Enter your rating <0-10>: 4
Enter next movie title (or enter to quit):
Here is the list of films:
Movie: SG, Rating: 4
Movie: sahhd, Rating: 32
Movie: aghah, Rating: 4
PS C:\Develop\c\c> ^C
PS C:\Develop\c\c> ^C
PS C:\Develop\c\c> gcc .\film2.c -o film2
PS C:\Develop\c\c> .\film2.exe
Enter first movie title (or enter to quit): asg
Enter your rating <0-10>: 4
Enter next movie title (or enter to quit): adeha
Enter your rating <0-10>: 3
Enter next movie title (or enter to quit):
Here is the list of films:
Movie: asg, Rating: 4
Movie: adeha, Rating: 3
Movie: aash, Rating: 3
freeing memory for asg
PS C:\Develop\c\c> .\film2.exe
Enter first movie title (or enter to quit): gag
Enter your rating <0-10>: 3
Enter next movie title (or enter to quit):
Here is the list of films:
Movie: gag, Rating: 3
freeing memory for gag
freeing memory for eD
PS C:\Develop\c\c>
PS C:\Develop\c\c>
PS C:\Develop\c\c> gcc .\film2.c -o film2
Enter next movie title (or enter to quit): adehg
Enter your rating <0-10>: 32
Enter next movie title (or enter to quit):
Here is the list of films:
Movie: asg, Rating: 326
Movie: adehg, Rating: 32
freeing memory for asg
freeing memory for }5P
freeing memory for adehg
PS C:\Develop\c\c>
PS C:\Develop\c\c>
PS C:\Develop\c\c>
PS C:\Develop\c\c>


PS C:\KuGou\mp4> C:\Develop\c\c\film2.exe
Enter first movie title (or enter to quit): sgag
Enter your rating <0-10>: 3
Enter your rating <0-10>: 4
Enter next movie title (or enter to quit): jpsn
Enter next movie title (or enter to quit):
Here is the list of films:
Movie: sgag, Rating: 3
Movie: ahjkjoa, Rating: 4
Movie: jpsn, Rating: 56
freeing memory for sgag
freeing memory for 锢z
freeing memory for ahjkjoa
freeing memory for jpsn
PS C:\KuGou\mp4> C:\Develop\c\c\film2.exe
Enter first movie title (or enter to quit): dfsj
Enter your rating <0-10>: 3
Enter next movie title (or enter to quit): jopiap
Enter your rating <0-10>: 4
Enter next movie title (or enter to quit): irwal
Enter your rating <0-10>: 6
Enter next movie title (or enter to quit):
Here is the list of films:
Movie: dfsj, Rating: 3
Movie: jopiap, Rating: 4
Movie: irwal, Rating: 6
freeing memory for dfsj
freeing memory for 谟I
freeing memory for jopiap
freeing memory for irwal


并且程序在打印最后一句“freeing memory for irwal”后要等待几十秒才能退出

起初我以为 free() 运行时代码被破坏,或者缓冲区没有刷新,所以我添加了这两行:

printf("freeing memory for %s\n", current->title);
fflush(stdout);
但新的问题又出现了: 为什么为一个不存在的结构释放了内存,而程序仍然正常释放内存? 为什么??????

c error-handling
1个回答
0
投票

问题出在这个循环中:

while (current!= NULL)
{
    printf("freeing memory for %s\n", current->title);
    current=head;
    head=head->next;
    free(current);
}

调用

free(current)
后,
current
所指向的内存不再有效。因此,当您使用
current->title
时,下一次迭代您将访问该无效内存并具有 未定义的行为

您需要更改做事的顺序:

while (current!= NULL)
{
    printf("freeing memory for %s\n", current->title);
    head=head->next;  // Get the next node in the list
    free(current);    // Free the current node
    current=head;     // Make the next node the current node
}
© www.soinside.com 2019 - 2024. All rights reserved.