c - 添加到链表时释放临时节点

标签 c struct linked-list malloc free

我有一个名为 addMod 的函数当调用时,将节点添加到 Module 数组的某个索引中名为 modules 的 struct LinkedLists包含在 System 中结构。一个Module struct 有一个字符串字段、两个 int 字段和一个指向下一个 Module 的指针。 ,前三个字段根据 addMod 中提供的参数进行初始化。 addMod大致看起来像这样:

int addMod(System *system, const char *text, int num1, int num2, int index) {
    Module *temp = malloc(sizeof(Module));
    Module *current;
    temp->next = NULL;

    if ([any of the constructors are invalid]) return 0;

    temp->text = malloc(strlen(text)+1);
    strcpy(temp->text, text);
    temp->num1 = num1; temp->num2 = num2;

    if (!system->modules[index]) {
        system->modules[index] = temp; //If there are no modules in the LinkedList at the given index, makes the head = temp.
    }
    else {
        if (system->compare(temp, system->modules[index]) <= 0) { //compare is a func pointer field of system that compares two Modules to see in what order they should be. Here, we check if temp should become the head of modules[index].
            temp->next = system->modules[index]; //Assigns the current head as the module following temp.
            system->modules[index] = temp; //Makes temp the current head.
        }
        else {
            current = system->modules[index];
            while (current->next && system->compare(temp, current->next) > 0) { //While current isn't the last node in the LinkedList and temp comes after the node after current
                current = current->next;
             }
            temp->next = current->next; //Adds temp in between current and current->next.
            current->next = temp;
        }
    }
    return 1;
}

以上所有内容均按预期工作,但打印 system 的内容时除外,控制台指示存在内存泄漏,我假设是因为我未能正确释放 temp根据 valgrind 告诉我的。我的问题是不知道在哪里释放它 - 似乎在我放置的任何地方都会在打印内容后导致段错误。根据我的理解,我必须确保没有其他变量依赖于 temp 所持有的值。 ,但考虑到 if 语句的每种可能的结尾都会导致分配 temp ,我似乎找不到一种方法来做到这一点到 modules 内的节点。推杆free(temp)逻辑和 return 1 之间我假设还会产生段错误,因为我经常 malloc temp再次调用addMod时连续多次。

总而言之,要将一个新节点添加到可能已填充或未填充的 LinkedList 中(其中该新节点可以插入到 LinkedList 中的任意位置),我必须将内存分配给临时节点,以便我可以稍后插入。成功插入节点后,我在哪里释放分配的内存?

最佳答案

假设您对 System 实例的管理是健全的(这是一个很大的假设,因为我看不到该代码),您在 temp 的内存分配中存在巨大的漏洞在“构造函数”检查失败的情况下,随后的硬返回0。更重要的是:

Module *temp = malloc(sizeof(Module)); // memory allocated here...
Module *current;
temp->next = NULL;

if ([any of the constructors are invalid]) 
    return 0; // and leaked here.

这可能就像交换支票一样简单。显然,还应该考虑和评估其他应该释放动态分配的代码。

<小时/>

更简单的方法

节点添加代码很复杂,但其实并不需要如此。最后,您真正应该关心的是找到新节点所在的位置。

  1. 如果表中的槽为空,则它是该列表中的第一个节点。
  2. 如果表中的槽不为空,则找到已排序的位置并将其插入那里。

这两个都可以通过使用指针到指针的单个 while 循环来完成,其中所述实体保存将在 中保存新节点的指针的地址上述任何一种情况,作为奖励,手术插入实际上是两项任务。

就这样完成了。请注意,大部分代码只是安全地创建 Module 对象。实际的插入只是一个 while 循环和一些指针赋值。它假设 System 中的表最初包含 NULL 条目:

int addMod(System *system, const char *text, int num1, int num2, int index)
{
    // allocate new node here
    Module *temp = malloc(sizeof *temp);
    if (temp == NULL)
    {
        perror("Failed to allocate new Module");
        return 0;
    }


    size_t len = strlen(text);
    temp->text = malloc(len + 1);
    if (temp->text == NULL)
    {
        perror("Failed to allocate module name");
        free(temp);
        return 0;
    }

    // finish copying member data
    memcpy(temp->text, text, len);
    temp->text[len] = 0;
    temp->num1 = num1;
    temp->num2 = num2;

    // now find where it belongs, and set next appropriately    
    Module **pp = system->modules + index;
    while (*pp && system->compare(temp, *pp) <= 0)
        pp = &(*pp)->next;

    temp->next = *pp;
    *pp = temp;
    return 1;
}

理解这是从我认为您的System类型的外观得出的,因为它从未出现过:

typedef struct System
{
    Module *modules[MAX_MODULES];
    int (*compare)(const Module* lhs, const Module *rhs);

} System;

我相当有信心它与此类似。当然,如果不是的话,你就必须适应。我建议您查看此内容并在调试器中逐步执行它。观看直播是无可替代的。

祝你好运。

关于c - 添加到链表时释放临时节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56591525/

相关文章:

c - 读取字符时会不会出现编码错误?

c - C中的填充矩阵

c - 绘图算法

go - 如何将断言临时结构键入具体结构

使用 open() 或 creat() 创建的文件设置的权限比我要求的要少

对如何添加到另一个结构中的链表结构感到困惑

c - 在 C 中查找结构的定义

java - 完成链表排序后,我不确定如何跳出循环

c - 如何修复打印链表时的段错误?

c++ - C++链表问题。数据类型之间有冲突?没有匹配的构造函数?