c中的免费记忆并获得免费(& p->数据)不起作用的未知错误

时间:2018-01-31 16:37:41

标签: c free

我在这里有一个节点结构:

struct N *mknode(struct N *xp, struct N *yp, struct N *zp, long n)
{
    struct N *p = malloc(sizeof(struct N));
    p->x = xp;
    p->y = yp;
    p->z = zp;
    p->data = n;
    return p;
}

我的任务是将每个节点完全释放一次,这样既没有双重释放也没有内存泄漏

我的代码只能包含stdlib.h和" freegraph.h",我把stdio.h放了,因为我需要使用printf函数来显示哪行代码不能正常工作

#include <stdlib.h>
#include "freegraph.h"

#include <stdio.h>

// construct a linked list
typedef struct node {
    struct N * val;
    struct node * next;
} node_t;

typedef enum { false, true } bool;

node_t head = { NULL, NULL };


// check if any duplicated in the linked list
bool check_duplicate (node_t * head, struct N * val) {
    bool duplicate = false;
    node_t * current = head;

    while (current != NULL) {
        if ( current->val == val) {
            duplicate = true;
            return duplicate;
        }
        else {
            current = current->next;
        }
    }
    return duplicate;
}

// adding an item to the end of the linked list
void push (node_t * head, struct N * val) {
    node_t * current = head;
    while (current->next != NULL) {
        current = current->next;
    }
    current->next = malloc(sizeof(node_t));
    current->next->val = val;
    current->next->next = NULL;
}
//deallocate recursive function, printf to see which line is working
void deallocate(struct N *p)
{
    if (p != NULL) {
        if (!check_duplicate(&head, p)) {
            deallocate (p->x);
            printf("1\n");
            deallocate (p->y);
            printf("2\n");
            deallocate (p->z);
            printf("3\n");
            free(&p->data);
            printf("4\n");
            push (&head, p);
            printf("5\n");
        }
    }

}

但是我的程序只打印1,2,3然后它会停止并退出。 所以我假设免费(&amp; p-&gt;数据)不起作用,但我真的不知道我做错了什么。

这是我的测试代码:

    p1 = mknode(NULL, NULL, NULL, 1);
    p2 = mknode(NULL, NULL, NULL, 10);
    p3 = mknode(NULL, NULL, NULL, 100);
    p4 = mknode(p1, p2, p3, 3000);
    p1 = mknode(NULL, NULL, NULL, 1);
    p2 = mknode(NULL, NULL, NULL, 10);
    p3 = mknode(NULL, NULL, NULL, 100);
    p5 = mknode(p1, p2, p3, 4000);
    p5 = mknode(p4, p5, NULL, 50000);
    p6 = mknode(p5, NULL, NULL, 100000);

    // now make it harder by sharing and cycles
    p1->x = p5;
    p2->y = p4;
    p2->z = p2;
    p6->y = p5;
    p6->z = p6; 

    deallocate(p6);

1 个答案:

答案 0 :(得分:0)

鉴于不能对提供的函数和数据类型进行其他修改,有效解决此问题所需的(抽象)数据结构是 set 。它们始终只包含每个唯一元素的一个副本。

步骤:

  • 创建一个空集
  • 在给定的起始节点上执行递归的深度优先搜索
  • 对于访问过的每个节点,如果集合包含它,则停止递归,否则将其添加到集合中并继续
  • 递归完成后,在集合中的每个节点上调用free(不对子指针做任何事情)

C风格的伪代码:

static void dealloc_recursive(struct N *p, Set* s)
{
   if (p == NULL) return;

   if (set_contains(s, p)) return;

   dealloc_recursive(p->x, s);
   dealloc_recursive(p->y, s);
   dealloc_recursive(p->z, s);
}

void deallocate(struct N *p)
{
   Set* set = set_create_empty();

   dealloc_recursive(p, set);

   for (struct N *p in set)
      free(p);

   set_destroy(set);
}

我想到了两种常见类型的集合(存在于Java库中;有关C解决方案的更多信息,请参阅this post):

  • 哈希集:哈希表。遏制查询是(摊销的)常量时间。可能会使用更多内存来解决冲突和链接。
  • 树集:一个(平衡的)二叉搜索树(通常)。遏制查询是对数时间。为节点元数据使用固定百分比的内存。

快速Google搜索会产生this示例实施。如果您有非常多的节点,请考虑使用 Judy数组。有无数其他人,可能更有效率。