【问题标题】:How to call free() properly?如何正确调用 free()?
【发布时间】:2020-08-25 14:23:26
【问题描述】:

请阅读整篇文章,因为其中包含非常重要的小细节。

正如 C 所知道的,我们应该处理 malloc 失败的事件,对于这种情况,我创建了一个名为 destroyList() 的函数,其工作是获取指向 Node 的指针并一个一个地销毁它。 但是我的函数没有被正确调用...

我尝试使用 ptr、merged_out*merged_out 调用它(最后一个是社区成员的建议),但似乎没有任何效果。

这是为什么?该函数有时会收到NULL、空列表或一些随机值。

有人可以帮我解决这个问题并让我了解发生了什么吗?

typedef struct node_t {
    int x;
    struct node_t *next;
} *Node;

void destroyList(Node ptr) {
    while (ptr) {
        Node toDelete = ptr;
        ptr = ptr->next;
        free(toDelete);
    }
}

主要功能:

ErrorCode mergeSortedLists(Node list1, Node list2, Node *merged_out) {
    if (!list1 || !list2) {
        return EMPTY_LIST;
    }
    if (!isListSorted(list1) || !isListSorted(list2)) {
        return UNSORTED_LIST;
    }
    if (!merged_out) {
        return NULL_ARGUMENT;
    }
    Node ptr = NULL;
    int total_len = getListLength(list1) + getListLength(list2);
    for (int i = 0; i < total_len; i++) {
        int min = getMin(&list1, &list2);
        ptr = malloc(sizeof(*ptr));
        *merged_out = ptr;
        if (!ptr) {
            destroyList(*merged_out);
            *merged_out = NULL;
            return MEMORY_ERROR;
        }
        ptr->x = min;
        ptr->next = NULL;
        merged_out = &ptr->next;
    }
    return SUCCESS;
}

函数的调用方式如下:

Node merged_actual = NULL;
ErrorCode merge_status = mergeSortedLists(list1, list2, &merged_actual);

注意getMin() 获取最小值并将具有该最小值的列表指针前进到下一个节点。

【问题讨论】:

  • err 我明白为什么......你需要用列表的头部调用destroy list,而不是merged_out,因为它指向列表的最后一个元素......
  • 在第一次调用时声明一个静态变量或存储 head 的东西。喜欢static Node head; static int flag=0; if (!flag){head=*merged_out;flag=1;}
  • 但我怎么能这样做,我花了 3 天时间,根本没有解决办法
  • 我不允许使用静态或全局变量
  • @AdrianMole 抱歉,我知道其中的区别,但无法指向代码中的第一个节点

标签: c memory-leaks malloc free c99


【解决方案1】:

if 检查之后开始。

    Node ptr=NULL,last;
    /* find out current tail of the list */
    if (*merged_out!=NULL){
        last=*merged_out;
        while (last->next!=NULL){
            last=last->next;
        }
    }
    int total_len = getListLength(list1) + getListLength(list2);
    for (int i = 0; i < total_len; i++)
    {
        int min = getMin(&list1, &list2);
        ptr = malloc(sizeof(*ptr));
        if (!ptr)
        {
            destroyList(*merged_out);
            *merged_out=NULL;
            return MEMORY_ERROR;
        }
        ptr->x = min;
        ptr->next = NULL;
        /* link ptr onto the list */
        if (*merged_out==NULL){
            /* if the list is empty, make ptr the head of the list */
            *merged_out=ptr;
            last=*merged_out;
        }
        else{
            last->next = ptr;
            last = ptr;
        }
    }

请尽量不要复制粘贴此代码块。它可能正确也可能不正确,但请尝试理解它的作用:每次调用函数时都进行迭代,以使last 指向列表的最后一个元素。因此merged_out总是可以指向头部。

【讨论】:

  • @smith_97 if (*merged_out==NULL){ *merged_out=ptr; ptr-&gt;next=NULL; last=*merged_out; } 所以第一个ptr变成*merged_out如果它是NULL
  • 我做了一些编辑,但代码仍然无法运行,它变得非常复杂
  • 它似乎有效,请您尝试简化它或使其更清晰(鉴于 *mergedout=NULL 当我调用函数和其他东西时)?
【解决方案2】:

@user12986714 我丢失了旧帐户,并被告知不要关心 *merged_out 的初始值,您能否更新解决方案(删除第一个 while 循环,不需要 2 个指针)

【讨论】:

  • 1) ping 某人的答案不起作用,我也没有收到任何通知。下次您可能想使用 cmets 2) 真的吗?我不相信。否则你为什么要对你自己的问题发布令人反感的答案? this one
  • 我也看不出编辑答案的必要性;您已经知道该怎么做了,所以只需在您的计算机上编辑代码并提交编辑后的版本
猜你喜欢
  • 2021-09-12
  • 2015-07-20
  • 1970-01-01
  • 1970-01-01
  • 2015-06-09
  • 1970-01-01
  • 2013-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多