双向链表代码出现指针访问违规错误的问题排查请求
排查双向链表实现中的指针访问违规问题
错误直接原因
触发访问违规的核心原因是传入了指向未初始化堆内存的野指针,代码中pstan的值为0xCDCDCDCD(Visual Studio环境下未初始化堆内存的标记值),导致尝试访问pstan->data时触发内存访问错误。
具体问题分析
1. 新节点的指针未初始化
使用malloc创建Node时,仅设置了data字段,但prev和next指针未初始化,默认是堆内存的随机垃圾值(非NULL)。后续判断pstan->prev != NULL或pstan->next != NULL时,会误将垃圾值当作有效指针,触发递归调用传入野指针。
2. Assort函数的分支条件错误
在cur->data >= pstan->data的分支中,递归判断条件错误地写成了pstan->prev != NULL,正确逻辑应该是判断pstan->next != NULL,否则会错误地往prev方向递归,而非预期的next方向。
3. 插入节点时未维护双向链表的指针关系
当将新节点挂载到目标节点的prev或next时,仅设置了目标节点的指针,未同步设置新节点的对应指针(比如pstan->prev = cur后,未设置cur->next = pstan和cur->prev = NULL),导致链表指针不完整,后续操作出现异常。
4. 函数形参的值传递误区
Assort函数中pstan = cur是修改函数内部的形参,不会影响main函数中pStan变量的值。不过main函数后续通过pStan = pRoot修正了这个问题,未引发直接错误,但需要注意C语言参数传递的特性。
修正后的代码
#include <stdio.h> #include <stdlib.h> struct Node { int data; struct Node* prev; struct Node* next; }; struct Node* pRoot = NULL; void Inorder(struct Node* root) { if (root == NULL) { return; } // 先遍历左(prev)侧 Inorder(root->prev); printf("%d ", root->data); // 再遍历右(next)侧 Inorder(root->next); } void Assort(struct Node* cur, struct Node* pstan) { if (pRoot == NULL) { pRoot = cur; // 初始化根节点的双向指针为NULL cur->prev = NULL; cur->next = NULL; } else { if (cur->data < pstan->data) { if (pstan->prev == NULL) { // 将cur挂载到pstan的prev位置 pstan->prev = cur; cur->next = pstan; cur->prev = NULL; } else { // 递归往前找合适位置 Assort(cur, pstan->prev); } } else { if (pstan->next == NULL) { // 将cur挂载到pstan的next位置 pstan->next = cur; cur->prev = pstan; cur->next = NULL; } else { // 递归往后找合适位置 Assort(cur, pstan->next); } } } } int main() { struct Node* pStan = NULL; for (int i = 0; i < 5; i++) { struct Node* Current = (struct Node*)malloc(sizeof(struct Node)); printf("정수를 입력하세요.\n"); scanf("%d", &Current->data); Assort(Current, pStan); pStan = pRoot; } Inorder(pRoot); return 0; }
修正点说明
- 新增了
Inorder函数的空指针判断,避免传入NULL时触发错误。 - 创建新节点后,在Assort函数中初始化根节点的
prev和next为NULL,非根节点挂载时同步维护双向指针关系。 - 修正了Assort函数中递归分支的条件错误,确保往正确的方向递归查找插入位置。
- 移除了不必要的调试语句,简化逻辑。
内容的提问来源于stack exchange,提问作者ty par
相关产品推荐
相关产品推荐

