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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 04:39:18