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

C++链表删除重复节点时出现指针访问冲突(0xDDDDDDDD)的原因排查咨询

链表去重代码的问题分析与修复方案

看起来你在实现链表重复节点删除的时候碰到了内存访问的坑,我来帮你拆解问题根源,再给出可运行的修正代码~

为什么会出现read access violation?

你看到的ptr2变成0xDDDDDDDD是微软VC编译器的特殊标记——它表示这块内存已经被释放了。问题主要出在这几个地方:

  • 内层循环条件写漏了最后一个节点:
    你写的while (ptr2 != NULL && ptr2->next != NULL)会直接跳过链表的最后一个节点。比如当ptr2指向最后一个20时,ptr2->next是NULL,循环直接终止,根本不会检查这个节点和ptr1是否重复。

  • 删除节点时没维护链表的链接:
    当你找到重复节点ptr2时,直接delete(dup)但没修改前一个节点的next指针。举个例子:假设链表是ptr1 -> ptr2 -> next_node,你删了ptr2之后,ptr1->next依然指向已经被释放的ptr2内存,后续遍历的时候访问这个地址就会触发内存访问违规。而且你直接把ptr2改成ptr2->next,原来的链表链接已经断了,下次循环必然踩坑。

  • 内层循环没跟踪前一个节点:
    你每次内层循环从ptr1->next开始,但没记录ptr2的前一个节点,导致删完节点后没法把前后节点连起来,链表直接断成好几段。


修正后的完整代码

我把你的代码补全了辅助函数(push、printList、deleteList),同时修复了核心逻辑:

#include <iostream>
using namespace std;

class Node {
public:
    int data;
    Node *next;
};

// 在链表头部插入节点的辅助函数
void push(Node** head_ref, int new_data) {
    Node* new_node = new Node();
    new_node->data = new_data;
    new_node->next = (*head_ref);
    (*head_ref) = new_node;
}

// 打印链表的辅助函数
void printList(Node *node) {
    while (node != NULL) {
        cout << node->data << " ";
        node = node->next;
    }
    cout << endl;
}

// 销毁整个链表的辅助函数
void deleteList(Node** head_ref) {
    Node* current = *head_ref;
    Node* next;
    while (current != NULL) {
        next = current->next;
        delete current;
        current = next;
    }
    *head_ref = NULL;
}

void removeDuplicatesAlpha(Node* start) {
    Node* ptr1 = start;
    Node* ptr2;
    Node* dup;

    // 外层循环逐个遍历每个节点
    while (ptr1 != NULL && ptr1->next != NULL) {
        ptr2 = ptr1;  // 让ptr2从ptr1开始,跟踪当前节点的前一个节点

        // 内层循环遍历ptr1之后的所有节点
        while (ptr2->next != NULL) {
            // 如果找到和ptr1重复的节点
            if (ptr1->data == ptr2->next->data) {
                dup = ptr2->next;
                // 先把前一个节点的next指向重复节点的下一个,维护链表链接
                ptr2->next = ptr2->next->next;
                delete dup;  // 释放重复节点的内存
            } else {
                ptr2 = ptr2->next;  // 没重复就移动到下一个节点
            }
        }
        ptr1 = ptr1->next;
    }
}

int main() {
    Node* head = NULL;
    push(&head, 3);
    push(&head, 3);
    push(&head, 20);
    push(&head, 14);
    push(&head, 9);
    push(&head, 20);
    push(&head, 20);

    cout << "原链表: ";
    printList(head);

    removeDuplicatesAlpha(head);

    cout << "删除重复后的链表: ";
    printList(head);

    deleteList(&head);
    return 0;
}

关键修复点说明

  1. 修正内层循环逻辑:
    把内层循环改成while (ptr2->next != NULL),这样能遍历到链表的最后一个节点,不会漏掉任何重复项。同时让ptr2从ptr1开始,方便跟踪前一个节点,删除时能正确维护链表链接。

  2. 正确维护链表链接:
    发现重复节点时,先让前一个节点的next跳过重复节点,再删除重复节点,这样链表不会断裂,也不会出现指向已释放内存的情况。

  3. 彻底避免访问已释放内存:
    不再直接修改ptr2为已删除节点的next,而是通过前一个节点的next来跳转,从根源上避免了踩0xDDDDDDDD这类已释放内存的坑。

运行修正后的代码,你会得到正确的输出:

原链表: 20 20 9 14 20 3 3 
删除重复后的链表: 20 9 14 3 

内容的提问来源于stack exchange,提问作者Alexandru Manolache

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 05:17:46