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

链表节点释放导致while(1)循环随机退出问题求助

双向链表随机崩溃问题排查

问题描述

实现双向链表节点操作时,程序正常运行3-7次后随机退出while(1)循环,调试时崩溃位置有时在free()处,有时在cur->prev相关的else分支中。程序本应持续运行直到按下Ctrl+C。

相关代码

链表节点处理函数

node *print_immu(node *root, unsigned char *map[HEIGHT], player *enemy){// need to check
    if(root != NULL){
       node *cur = root;
        node *tmp;  
        while(cur->next != NULL){      //if there are many > 
            if(cur->width == WIDTH - 1 || map[cur->height][cur->width + 2] == '#'){
                if(map[cur->height][cur->width + 2] == '#'){
                    enemy->lives--;
                }
                tmp = cur;
                if(tmp->prev == NULL){
                    root = cur->next;
                    tmp->next->prev = NULL;
                }else{
                    tmp->next->prev = tmp->prev;
                    tmp->prev->next = tmp->next;
                }
                map[cur->height][cur->width] = '`';
                cur = cur->next;
                free(tmp);
                
            }else{
                map[cur->height][cur->width] = '`';
                cur->width += 2;       
                map[cur->height][cur->width] = '>';
                cur = cur->next;
            }
        }   
        tmp = cur;
        if(cur->width == WIDTH - 1 || map[cur->height][cur->width + 2] == '#'){
            if(map[cur->height][cur->width + 2] == '#'){
                enemy->lives--;
            }
            if(cur->prev == NULL){
                map[cur->height][cur->width] = '`';
                free(cur);
                root = NULL;
            }else{
                map[cur->height][cur->width] = '`';
                tmp = tmp->prev;
                free(cur);
                tmp->next = NULL;
           }
        }else{
            map[cur->height][cur->width] = '`';
            cur->width += 2;
            map[cur->height][cur->width] = '>';
        }
    }
    return
}

节点创建函数

node *players_u(player *me, node *root, unsigned char *map[HEIGHT]){
    for(int i=0; i<me->size; i++){
        if(map[me->height + i][1] == '+'){
            if(me->block == '#'){
                me->lives--;
            }else{  
                if(root == NULL){
                    root = (node*)malloc (sizeof(node*));
                    root->next = NULL;
                    root->prev = NULL;
                }else{
                    node *nw = (node*)malloc (sizeof(node*));
                    nw->next = root;
                    root->prev = nw;
                    root = nw;   
                    nw->prev = NULL;
                }
                root->height = me->height + i;
                root->width = 1;
            }
        }
    }
    return root;
}

排查及修复建议

1. 内存分配错误(核心根因)

在players_u函数中,malloc时错误地分配了指针大小(sizeof(node*)),而非node结构体的完整大小:

root = (node*)malloc (sizeof(node*));  // 错误:仅分配了指针的字节数
node *nw = (node*)malloc (sizeof(node*));  // 同样错误

这会导致结构体成员(height、width、prev、next)越界覆盖相邻内存,随机损坏链表指针,引发后续free()或指针访问崩溃。修复为:

root = (node*)malloc(sizeof(node));
node *nw = (node*)malloc(sizeof(node));

2. 函数返回值缺失

print_immu函数末尾的return没有返回值,但函数声明要求返回node*类型,这会导致调用方拿到无效的垃圾地址,后续操作链表必然崩溃。修复为:

return root;

3. 数组越界访问风险

print_immu中,当cur->width接近WIDTH时,cur->width + 2可能超出map数组的宽度范围,引发非法内存访问:

if(cur->width == WIDTH - 1 || map[cur->height][cur->width + 2] == '#')

添加边界判断后修复:

bool has_obstacle = (cur->width + 2 < WIDTH) && (map[cur->height][cur->width + 2] == '#');
if(cur->width == WIDTH - 1 || has_obstacle)

4. 链表操作校验

在删除节点后,确保cur指针未指向已释放内存;每次修改链表的prev/next关联后,打印指针地址校验双向关联是否正确,避免出现野指针。

辅助调试方法

  • 启用编译器内存检测(如GCC的-fsanitize=address),直接定位内存越界、重复释放等问题。
  • 在malloc和free时打印指针地址,检查是否存在重复释放或释放未分配内存的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 09:14:52