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

双向链表删除节点触发Segmentation fault问题求助

双向链表Segmentation Fault问题排查

我在操作双向链表时持续出现Segmentation fault错误,该错误似乎由remove()和size()函数引发。调试时发现传入remove()的pos参数与main函数中传入的不一致,相关代码如下:

头文件 linked_list.hpp

#ifndef linked_list_hpp
#define linked_list_hpp

#include <stdio.h>

class linked_list {
private:
    class Node {
    public:
        double data;
        Node *next;
        Node *prev;

        Node(double data);
    };

    Node *head;
    Node *tail;

public:
    size_t size() const;
    linked_list();
    double back() const;
    double at(size_t index) const;  // 修正参数类型
    void push_back(double value);
    bool is_empty() const;
    void print() const;
    void remove(size_t pos);  // 修正参数类型
};
#endif /* linked_list_h */

实现文件 linked_list.cpp

#include "linked_list.h"
#include <iostream>
#include <stdexcept>
#include <algorithm>

linked_list::linked_list(){
    head = nullptr;
    tail = nullptr;
}

linked_list::Node::Node(double data){
    this->data = data;
    this->next = nullptr;
    this->prev = nullptr;
}

bool linked_list::is_empty() const{
    return (head == nullptr && tail == nullptr);
}

double linked_list::back() const {
    if (is_empty()) {
        throw std::out_of_range("Empty list");
    }
    return tail->data;
}

double linked_list::at(size_t index) const{
    if (index >= size()) {
        throw std::out_of_range("Index out of range");
    }

    size_t i = 0;
    Node* curr = head;
    while(curr != nullptr && i != index){
        curr = curr->next;
        i++;
    }
    return curr->data;
}

void linked_list::remove(size_t pos) {
    if (pos >= size()) {
        throw std::out_of_range("Index out of range");
    }

    Node* curr = head;
    for (size_t i = 0; i < pos; i++) {
        curr = curr->next;
    }

    // 处理前驱节点
    if (curr->prev != nullptr) {
        curr->prev->next = curr->next;
    } else {
        // 删除的是头节点,更新head
        head = curr->next;
    }

    // 处理后继节点
    if (curr->next != nullptr) {
        curr->next->prev = curr->prev;
    } else {
        // 删除的是尾节点,更新tail
        tail = curr->prev;
    }

    delete curr;

    // 链表为空时,确保head和tail都置空
    if (head == nullptr) {
        tail = nullptr;
    }
}

void linked_list::push_back(double value){
    Node* new_node = new Node(value);
    if(is_empty()){
        head = new_node;
        tail = new_node;
        return;
    }
    tail->next = new_node;
    new_node->prev = tail;
    tail = new_node;
}

size_t linked_list::size() const {
    size_t elements = 0;
    Node* temp = head; 
    while (temp != nullptr) {
        elements++;
        temp = temp->next; 
    }
    return elements;
}

void linked_list::print() const{
    Node *temp = head;
    while (temp != nullptr) {
        std::cout << temp->data << " ";
        temp = temp->next;
    }
    std::cout << std::endl;
}

主文件 main.cpp

#include <iostream>
#include "linked_list.h"
#include <cstdlib>
#include <ctime>
#include <chrono>

int main() {
    linked_list ls1;
    auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
    srand(seed);

    ls1.push_back(0);
    for (int i = 1; i < 50; i++) {
        int last_num = ls1.back();
        int next_num = rand() % 5 + last_num + 1;
        ls1.push_back(next_num);
    }

    // 要删除索引25的元素,直接传入索引值
    ls1.remove(25);

    // 如果需要按值删除,需新增对应函数,比如void remove_value(double value)
    // 实现逻辑为遍历链表找到对应值的节点再执行删除操作

    ls1.print();
    return 0;
}

问题根源与修复说明

  1. 核心用法错误:main函数中ls1.remove(list1_at_index25);传入的是节点的数值,但remove()函数设计为接收索引位置,参数完全不符合预期,直接引发越界访问导致Segmentation fault。
  2. 参数类型错误:remove()和at()的参数使用double不合理,索引是整数类型,应改为size_t(匹配容器大小的无符号整数)或int,避免浮点数精度丢失引发的索引错误。
  3. 尾节点更新缺失:原remove()函数删除最后一个节点时未更新tail指针,导致后续back()等函数访问已释放的内存地址。
  4. 空链表处理不完善:删除最后一个节点后,未将head和tail同时置为nullptr,可能导致is_empty()判断失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 13:01:59