空闲内存用于 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", ¤t->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->title
和current->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 教科书中都是不可接受的。
我 运行 来自清单 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", ¤t->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->title
和current->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 教科书中都是不可接受的。