15数码解谜C代码输出路径时触发段错误的修复请求
15数码谜题段错误排查与修复方案
核心问题定位
- 触发位置:
move_down函数因传入NULL指针pnode,访问其成员变量导致段错误 - 测试用命令行参数:
2 3 0 4 1 6 7 8 5 9 10 12 13 14 11 15
可能的根因
- 移动合法性未校验:当空白块(0)处于4x4网格的最底部行(索引12-15)时,无法执行向下移动操作,但代码仍调用了
move_down,且传入了无效的NULL节点 - 节点内存分配失败:复制当前节点状态的函数(如
copy_node)因内存不足返回NULL,后续代码未做判空处理就直接传入move_down - 搜索结构指针异常:使用BFS/DFS搜索时,队列/栈中弹出的节点已被提前释放,导致取出的指针为NULL
修复方案
1. 前置校验移动合法性
在调用move_down前,先检查节点有效性和空白块位置:
// 假设blank_pos为空白块的索引(0-15) if (pnode != NULL && blank_pos < 12) { // 仅前3行可向下移动 move_down(pnode); }
2. 函数内部增加防御性判空
在move_down函数开头添加NULL检查,避免非法内存访问:
void move_down(Node *pnode) { if (pnode == NULL) { fprintf(stderr, "Error: move_down received NULL node\n"); return; } // 原有移动逻辑代码 }
3. 修复节点复制逻辑
确保节点复制函数在内存分配失败时返回NULL,且调用处处理该情况:
Node* copy_node(Node *src) { if (src == NULL) return NULL; Node *new_node = malloc(sizeof(Node)); if (new_node == NULL) { perror("Failed to allocate memory for new node"); return NULL; } // 复制棋盘状态、父节点指针等成员 memcpy(new_node->board, src->board, sizeof(new_node->board)); new_node->parent = src; return new_node; }
调试辅助手段
- 在调用
move_down的位置添加日志,追踪指针状态和空白块位置:printf("Calling move_down: node addr=%p, blank_pos=%d\n", pnode, blank_pos); - 使用gdb执行
bt命令查看完整调用栈,准确定位传入NULL指针的上游代码行
内容的提问来源于stack exchange,提问作者Sebastian Llaurador
相关产品推荐
相关产品推荐

