【问题标题】:Struct node deallocation结构节点释放
【发布时间】:2013-09-30 22:45:18
【问题描述】:

我正在尝试从列表中删除一个结构节点,但我一直面临同样的问题。

typedef struct task{ 
  char* id;
  struct task *next;
} task_t;

task_t** init(){    
  task_t **taskArray = malloc(6 * sizeof(task_t *));
  return taskArray;
}

void task_insert(task_t ** arrayTask, char* id, int prio){
  task_t *newTask = (task_t *) malloc (sizeof(task_t));
  newTask->id = id;
  if(*(arrayTask + prio) !=NULL){
    newTask->next = *(arrayTask + prio);
    *(arrayTask + prio) = newTask;
    }
  *(arrayTask + prio) = newTask;

}

void task_remove(task_t** arrayTask, char* id){
  task_t* auxtask, * auxtask1;
  int i;
  for(i = 0; i<arraySize; i++){
    auxtask1 = auxtask = arrayTask[i];
    while(auxtask != NULL){
        if(!strcmp(auxtask->id, id)){
            auxtask1 = auxtask->next;
            free(auxtask);
            printf("Task %s removed with success\n", id);
            return;         
            }
        else {
            auxtask1 = auxtask;
            auxtask = auxtask->next;
             }

     }
   }
}   

当我尝试释放 auxtask 时出现问题。会发生什么以某种方式释放了 ID 字段,而不是结构节点本身。

有人知道这里发生了什么吗?

【问题讨论】:

    标签: c struct malloc free


    【解决方案1】:

    你忘记了一行:

    auxtask1 = auxtask->next;
    free(auxtask);
    auxtask = auxtask1;        // <-- here
    

    否则,您将释放auxtask,然后“忘记”它的下一个指针。下次循环时,您使用了auxtask,它指向已释放的内存。

    只是一个小问题...反过来使用临时工更正常。

    to_delete = auxtask;
    auxtask = auxtask->next;
    free(to_delete);
    

    【讨论】:

    • 但是我们不需要它的 next 指针,我们是否在 printf 之后立即从函数返回。我们只需要释放列表中的那个特定节点,奇怪的是我们只释放 id 字段(结构的)而不是结构节点本身。
    • 我的错,我很傻。你整理好了吗?当您 insert 列表中的第一项时,您确实有一个未初始化的 next 指针。 malloc 不 为您清除内存。分配NULL 或使用calloc。分配任务数组时也是如此。您必须清除该内存,因为您首先要依赖包含NULL 的空数组。
    【解决方案2】:

    我假设因为您的任务数组只是为指向 task_t 的指针分配空间,所以当您填充数组时,您在其他地方还有另一个分配步骤?

    另外,为什么你有一个作为数组访问的列表?为什么还要列一个清单?

    【讨论】:

    • 是的,我们有一个插入函数负责在用户插入新任务时填充数组。我将使用代码编辑问题。
    • 好的,那为什么newTask->next指向newTask呢?行:newTask->next = *(arrayTask + prio); *(arrayTask + prio) = newTask;看起来像我的循环分配?我必须假设 prio 是列表中前一个元素的索引,而您的下一个点“向后”是因为需要更好的描述。那么分配不应该是: newTask->next = *(arrayTask + prio); *(arrayTask + prio + 1) = newTask;
    • 再一次,我不得不问你为什么混合列表和数组类型访问?您为什么不直接删除 struct task *next 字段并将 struct 纯粹作为数组使用?
    • 不,我认为你看错了,我必须确定方案,但基本上我们拥有的是一个带有指针的 6 位置数组,它执行 6 个不同的结构任务列表。 prio 是数组中的索引,插入是在每个列表的开头进行的,所以我们将 newTask->next 指针指向插入数组的指针所在的位置 *(arrayTask + prio) (基本上指向第一个元素在那个列表中),然后我们将这个 *(arrayTask + prio)(插入数组中的指针)指向 newTask。我认为我们做得对,但经过数小时的研究,我无法确定任何事情......
    • 啊,好吧,这更有意义。所以,第一件小事,你不需要在 if 子句中执行 *(arrayTask + prio) ,无论我是否正确阅读你的代码,它都会失败并执行它。其次,正如 paddy 所说,您需要在删除您感兴趣的元素后重新链接列表中的元素。我很好奇您是如何知道只有 id 被释放的?
    猜你喜欢
    • 2018-05-17
    • 1970-01-01
    • 2012-11-15
    • 2014-10-26
    • 2019-08-10
    • 1970-01-01
    • 1970-01-01
    • 2013-07-23
    相关资源
    最近更新 更多