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

C语言循环双向链表插入异常:新对象与已有对象地址重复

C语言循环双向链表插入异常:第二个元素插入时curr与prev地址重合

实现循环双向链表时,插入第一个元素功能正常,但插入第二个元素时,调试发现局部变量curr和prev的地址完全相同,导致链表结构异常。

问题代码

struct ListNode {
    void *item;
    struct ListNode *next;
    struct ListNode *prev;
};

struct List {
    int num_members;
    ListNode head;

    /* function pointers */
    ...
};

int  ListAppend(List* list, void* item){
    ListNode* node = &(list->head);
    ListInsertBefore(list,item,node);
    
    return 0;
}

int  ListInsertBefore(List* list, void* item, ListNode* node){
    ListNode* prev = node->prev;
    ListNode curr;
    curr.item = item;
    
    node->prev = &curr;
    curr.next = node;
    prev->next = &curr;
    curr.prev = prev;

    list->num_members += 1;

    return 0;
}

GDB调试输出

62      curr.item = item;
7: node = (ListNode *) 0xbfffef08
8: *node = {item = 0x0, next = 0xbfffee70, prev = 0xbfffee70}
9: &curr = (ListNode *) 0xbfffee70
10: curr = {item = 0x0, next = 0xbfffef08, prev = 0xbfffef08}
11: prev = (ListNode *) 0xbfffee70
12: *prev = {item = 0x0, next = 0xbfffef08, prev = 0xbfffef08}

问题分析

核心错误出在ListInsertBefore函数里的ListNode curr;——这是栈上分配的局部变量。函数执行完毕返回后,栈上的curr会被销毁,其内存地址会被后续函数调用复用。
第一次插入时,curr的地址被赋值给head的prev和prev(也就是head自己)的next,此时链表暂时看起来正常,但这块内存已经不属于有效节点了。第二次调用ListInsertBefore时,新的curr刚好分配到了和第一次curr相同的栈地址,也就是此时prev指向的地址,导致&curr和prev地址重合,最终破坏链表结构。

修复方案

  1. 用动态内存分配创建节点:确保节点内存在函数返回后依然有效
int  ListInsertBefore(List* list, void* item, ListNode* node){
    ListNode* curr = malloc(sizeof(struct ListNode));
    if (!curr) {
        // 内存分配失败处理
        return -1;
    }
    curr->item = item;
    
    ListNode* prev = node->prev;
    node->prev = curr;
    curr->next = node;
    prev->next = curr;
    curr->prev = prev;

    list->num_members += 1;

    return 0;
}
  1. 初始化链表状态:创建List结构体后,需将head的next和prev指向自身,保证循环链表初始结构正确
void ListInit(List* list) {
    list->num_members = 0;
    list->head.next = &list->head;
    list->head.prev = &list->head;
}
  1. 补充销毁逻辑:后续需实现链表销毁函数,用free释放所有动态分配的节点,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 12:24:45