C++链表reverse函数空指针解引用警告问题排查
问题分析与修复
警告信息
Dereferencing NULL pointer. 'Node.link' contains the same NULL value as 'next' did. See line 74 for an earlier location where this can occur
触发场景
在LinkedList类的reverse函数第81行Node.link->link = nullptr;处触发该空指针解引用警告。其中Node用于存储链表节点总数并指向链表根节点,链表结构为Node->node0->node1->node2->....。
问题代码
#include <iostream> class LinkedList { // too lazy to make stuff private and write getters and setters. public: struct Node { unsigned int ival = 0; struct Node* link = nullptr; }; struct Node Node; LinkedList(unsigned int ival) { auto temp = new struct Node(); temp->ival = ival; Node.ival++; Node.link = temp; } void addNode(unsigned int pos, int ival) { struct Node* newNode = new struct Node(); newNode->ival = ival; switch (pos) { // create a new root node case 0: newNode->link = Node.link; Node.link = newNode; break; default: auto temp = Node.link; // go to the node before for (unsigned int i = 0; i < Node.ival - 1 && i < pos - 1; i++) { temp = temp->link; } // link the new Node newNode->link = temp->link; // insert node temp->link = newNode; } // increment only at the end Node.ival++; } void deleteNode(unsigned int pos) { // decrement before to indicate the node will be deleted or the for loop won't work; Node.ival--; struct Node* leak = nullptr; switch (pos) { case 0: // store for deletion to prevent leak leak = Node.link; // correct the links to omit the node to be deleted Node.link = Node.link->link; break; default: auto temp = Node.link; // go to the node before for (unsigned int i = 0; i < Node.ival - 1 && i < pos - 1; i++) { temp = temp->link; } // store for deletion to prevent leak leak = temp->link; // correct the links to omit the node to be deleted temp->link = temp->link->link; break; } delete leak; } void reverse(unsigned int begin, unsigned int end) { } void reverse() { // root node stored in prev auto prev = Node.link; // root->next in next auto next = prev->link; while (next != nullptr) { auto temp_store = next->link; next->link = prev; prev = next; next = temp_store; } Node.link->link = nullptr; Node.link = prev; } }; int main() { LinkedList linkedList(10); linkedList.addNode(3, 20); linkedList.addNode(1, 15); linkedList.addNode(0, 5); linkedList.addNode(-1, 25); linkedList.addNode(-1, 30); linkedList.reverse(); return 0; }
问题根源
reverse函数未处理链表为空或仅含一个节点的边界情况:
- 若链表为空(
Node.link == nullptr),prev = Node.link会赋值为nullptr,后续next = prev->link直接触发空指针访问; - 若链表仅含一个节点,
next = prev->link会赋值为nullptr,循环直接跳过,静态分析工具会识别到Node.link潜在的空指针风险(比如链表被清空后调用reverse)。
修复方案
在reverse函数开头添加边界判断,空链表或仅一个节点时直接返回,无需执行反转逻辑:
void reverse() { // 空链表或仅一个节点,无需反转 if (Node.link == nullptr || Node.link->link == nullptr) { return; } // root node stored in prev auto prev = Node.link; // root->next in next auto next = prev->link; while (next != nullptr) { auto temp_store = next->link; next->link = prev; prev = next; next = temp_store; } Node.link->link = nullptr; Node.link = prev; }
这样既避免了空指针解引用的风险,也优化了不必要的执行流程。
内容的提问来源于stack exchange,提问作者kesarling
相关产品推荐
相关产品推荐

