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

时间:2019-06-14 04:48:19

标签: c struct linked-list malloc free

我有一个名为addMod的函数,该函数在被调用时会将一个节点添加到Module中包含的modules结构System的结构LinkedList数组的某个索引中结构。 Module结构具有一个字符串字段,两个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也会产生段错误,因为连续多次调用temp时,我经常再次分配addMod

总而言之,要将一个新节点添加到可能填充或可能不填充的LinkedList中,并且可以在LinkedList中的任意位置插入该新节点,因此我必须为临时节点分配内存可以稍后再插入。成功插入节点后,该在哪里释放分配的内存?

1 个答案:

答案 0 :(得分:1)

假设您对System实例的管理是合理的(一个很大的假设,因为我看不到该代码),那么您在temp的内存分配中有一个巨大的漏洞,其后是硬{{1 }}在“构造函数”检查失败的情况下。更重要的是:

return 0

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


更简单的方法

节点添加代码是复杂的,并且不需要。最后,您真正需要关心的就是找到新节点所在的位置。

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

这两个都可以通过使用指向指针的指针在单个while循环中完成,其中所述实体保存将保存中新节点的指针的地址。

是这样完成的。请注意,大多数代码只是安全地制作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. 对象。实际的插入仅是一个while循环和一些指针分配。假设Module中的表最初包含NULL条目:

System

理解这是通过推导我认为您的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

我非常有信心与此相似。当然,如果没有的话,就必须适应。我建议您检查一下并在调试器中逐步进行。除了现场观看,别无选择。

好运。