You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言队列实现中的Double Free问题求助

解决C语言队列实现中的double free问题

问题根源

你的代码触发double free的核心原因有两个:

  1. queue_poll参数为值传递:函数内修改queue指针不会同步到外部变量。第一次poll释放头节点后,外部的queue指针仍指向已被free的内存(野指针)。
  2. 错误的头节点释放逻辑:当队列只剩最后一个元素时,直接free头节点,但后续操作(添加或再次poll)仍在使用这个野指针指向的内存,最终导致重复释放同一地址。

具体流程示例:

  • 调用new_queue()创建头节点(地址0x123),添加'A'后,头节点object指向'A',next为NULL。
  • 第一次queue_poll(queue):检测到next为NULL,free(0x123)并返回'A',但外部queue变量仍为0x123(野指针)。
  • 添加'B':调用queue_add(&B, queue),非法访问已释放的0x123内存,将object赋值为&B。
  • 第二次queue_poll(queue):再次尝试free(0x123),该地址已被释放过一次,触发double free错误。

修复方案

提供两种可行修复方式,按需选择:

方案1:传递指针的指针,维护外部队列有效性

修改queue_poll为二级指针参数,直接修改外部队列指针,避免野指针:

void* queue_poll(queue_object** queue) {
    if (queue == NULL || *queue == NULL) {
        return NULL;
    }

    queue_object* current = *queue;
    void* data = current->object;

    // 处理最后一个节点的情况
    if (current->next == NULL) {
        free(current);
        *queue = NULL; // 外部指针置空,防止后续误操作
    } else {
        *queue = current->next; // 外部指针指向新头节点
        free(current);
    }

    return data;
}

调用时需传入队列指针的地址:

queue_object* my_queue = new_queue();
// 添加元素逻辑...
void* data = queue_poll(&my_queue);

方案2:使用哨兵头节点(推荐)

保持头节点始终存在(仅在free_queue时释放),只释放后续节点,彻底避免野指针:

void* queue_poll(queue_object* queue) {
    if (queue == NULL || queue->object == NULL) {
        return NULL;
    }

    void* data = queue->object;

    // 队列只剩头节点有数据,清空即可,不释放头节点
    if (queue->next == NULL) {
        queue->object = NULL;
        return data;
    }

    // 将下一个节点的数据移到头部,释放下一个节点
    queue_object* tmp = queue->next;
    queue->object = tmp->object;
    queue->next = tmp->next;
    free(tmp);

    return data;
}

这种方式下,new_queue创建的头节点全程有效,free_queue会最终释放所有节点(包括头节点),无需修改调用方式。

额外注意事项

  • 方案1中,若外部队列指针被置为NULL,后续调用queue_add前需重新调用new_queue创建队列。
  • free_queue函数逻辑正确,会遍历释放所有节点,无需修改。

内容的提问来源于stack exchange,提问作者chiefsteve

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 05:35:26