C++执行while(p!=NULL)判空后程序无报错终止问题排查
问题根因
程序无报错直接终止是典型的内存非法访问触发段错误,代码里存在两个必现的致命bug:
- 必现空指针解引用:
while(p!=NULL)循环的终止条件是p == NULL,也就是说循环正常走完时p一定是空指针。但循环结束后第一行代码就直接访问p->unique,属于明确的空指针解引用,不管是第几次调用函数,只要链表遍历完成走到这行就会崩溃。你加的打印语句在while循环之前,所以能正常输出,崩溃点实际在循环结束后的解引用操作,因为编译优化带来的行号偏移,看起来像是程序停在while代码行。 - 新节点野指针问题:你用
new Node创建的新节点data没有初始化next成员,C++的new不会自动给结构体/类的成员赋默认值,data->next会是随机的野地址。如果只删掉空指针相关的错误代码,第二次调用函数遍历链表时,走到第一次插入的尾节点时,p = p->next会拿到野值,要么触发非法访问崩溃,要么出现死循环导致程序跑飞。
另外你第一次调用函数时,传入的*front初始值为NULL,while(p!=NULL)会直接跳过,还是会走到后面的空指针解引用逻辑,第一次调用就会触发崩溃。
修复方案
按以下步骤修改即可:
- 直接删除while循环结束后、
currentSolution.insert(s);之前的所有冗余代码,也就是这段完全错误的逻辑:
// 以下整段删除 currentShare = setIntersection(p->unique, data->unique); for (it = currentShare.begin(); it != currentShare.end(); ++it) { p->unique.erase(*it); p->shared.insert(*it); data->shared.insert(*it); }
这段逻辑没有任何存在的意义——while循环已经遍历完链表所有现存节点,完成了新节点和所有旧节点的交集计算、unique/shared属性更新,循环结束后p已经是空指针,后续访问p的代码全是错误逻辑。
2. 创建新节点后显式初始化next指针为NULL,避免野指针:
Node *data = new Node; data->S = s; data->unique = s; data->next = NULL; // 新增这行做初始化
修改后第一次插入节点时,尾节点next为空,后续遍历链表可以正常终止,不会出现野指针访问。
修复后完整的refreshOnDataEntry参考
void refreshOnDataEntry(set<string> s, Node **front, Node **rear, set<set<string>> ¤tSolution, set<string> &kSetUnion) { set<string> currentShare; Node *p = *front; Node *data = new Node; data->S = s; data->unique = s; data->next = NULL; // 初始化next指针 cout << "I'm about to die" << endl; while (p!=NULL) { currentShare = setIntersection(p->unique, data->unique); p->unique.erase(currentShare.begin(), currentShare.end()); p->shared.insert(currentShare.begin(), currentShare.end()); data->shared.insert(currentShare.begin(), currentShare.end()); p = p->next; } // 已删除冗余的空指针访问代码 currentSolution.insert(s); kSetUnion.insert(data->S.begin(), data->S.end()); if (*rear != NULL) (*rear)->next = data; else *front = data; *rear = data; }
内容的提问来源于stack exchange,提问作者Manuel Care
相关产品推荐
相关产品推荐

