c-如何解除链表的分配



这是我的代码。

struct node_struct {
char *data;
struct node_struct *next;
};
typedef struct node_struct Node;
struct queue_struct {
Node *head, *tail;
};
typedef struct queue_struct Queue;
void push(Queue **q, char *word) 
{
// q hasn't been allocated
if (*q == NULL) {
(*q) = malloc(sizeof(Queue));
}
Node *temp;
temp = malloc(sizeof(Node));
temp->data = malloc(sizeof(char)*strlen(word));
strcpy(temp->data, word);
temp->next = NULL;
if ((*q)->head == NULL) {
(*q)->head = (*q)->tail = temp;
}
else {
(*q)->tail->next = temp;
(*q)->tail = temp;
}
}

我将使用push将字符串字推送到队列q的后面除了保留指向数组的指针外,它还在队列中保留单词的副本。

最后,我想解除分配队列以及其中的所有项目。所以,我使用free(),这就是我所写的。

void delete(Queue *q) 
{
Node *temp;
for (temp = q->head; temp != NULL; temp = temp->next) {
free(temp->data);    
free(temp);
}
free(q);
}

但是,这会导致分割错误。为什么会发生这种情况,我该如何解决?

  1. malloc()字符串时,需要为终止的"\0"分配一个额外的字节
  2. delete()中,您需要在循环中有两个空闲,然后是一个空闲队列(与推送中的顺序相反;在这种情况下,从头部释放更容易(。这里需要临时变量t2来记住下一个元素,以便更新循环变量t
  3. 创建初始队列时需要初始化head
  4. (未修复(检查malloc()strdup()是否成功
#include <stdlib.h>
#include <string.h>
typedef struct node_struct {
char *data;
struct node_struct *next;
} Node;
typedef struct queue_struct {
Node *head;
Node *tail;
} Queue;
void push(Queue **q, const char *word) {
if (!*q) {
*q = malloc(sizeof(Queue));
(*q)->head = NULL;
}
Node *temp = malloc(sizeof(Node));
temp->data = malloc(strlen(word) + 1);
strcpy(temp->data, word);
temp->next = NULL;
if (!(*q)->head) {
(*q)->head = temp;
(*q)->tail = temp;
} else {
(*q)->tail->next = temp;
}
}
void delete(Queue *q) {
for(Node *t = q->head; t;) {
free(t->data);
Node *t2 = t->next;
free(t);
t = t2;
}
free(q);
}
int main(void) {
Queue *q = NULL;
push(&q, "test");
push(&q, "test2");
delete(q);
}

这是valgrind的输出:

==762222== HEAP SUMMARY:
==762222==     in use at exit: 0 bytes in 0 blocks
==762222==   total heap usage: 5 allocs, 5 frees, 59 bytes allocated
==762222== 
==762222== All heap blocks were freed -- no leaks are possible
==762222== 
==762222== For lists of detected and suppressed errors, rerun with: -s
==762222== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

为了简化push(),您可以使用指向Node(p(的双指针,calloc()初始化头,strdup()分配和复制字符串:

#define _POSIX_C_SOURCE 200809L // for strdup()
#include <string.h>
void push(Queue **q, const char *word) {
Node **p;
if (!*q) {
(*q) = calloc(1, sizeof(Queue));
p = &(*q)->tail;
} else
p = &(*q)->tail->next;
(*p) = malloc(sizeof(Node));
(*p)->data = strdup(word);
(*p)->next = NULL;

if (!(*q)->head)
(*q)->head = *p;
}

主要问题是您正在访问释放的数据:

for (temp = q->head; temp != NULL; temp = temp->next) {
free(temp->data);    
free(temp);
}

temp = temp->next被评估时,temp被释放。在释放结构之前,必须先捕获指针。一种方法是这样做(但还有其他等效的方法(。

temp = q->head;
while (temp != NULL)
{
free(temp->data);    
Node *next = temp->next;
free(temp);
temp = next;
}

你也在写越界:

temp->data = malloc(sizeof(char)*strlen(word));
strcpy(temp->data, word);

使用strdup()malloc(strlen(word) + 1);strcpy()放置在数据后面的空字节分配足够的空间。由于定义为sizeof(char) == 1,因此不需要乘以sizeof(char)

最新更新