list - 如何在这个简单的双向链表实现中修复 SIGSEGV?

标签 list pointers linked-list rust unsafe

我得到一个 SIGSEGV运行此代码时出错。

代码编译,调试器显示指针中的随机地址。

use std::ptr;

pub struct List<T> {
    head: *mut Node<T>,
    tail: *mut Node<T>,
}

struct Node<T> {
    data: Option<T>,
    next: *mut Node<T>,
    prev: *mut Node<T>,
}

impl<T> List<T> {
    pub fn new() -> Self {
        Self {
            head: ptr::null_mut(),
            tail: ptr::null_mut(),
        }
    }
    pub fn add_tail(&mut self, data: T) {
        let mut new_node = Box::new(Node {
            data: Some(data),
            next: ptr::null_mut(),
            prev: ptr::null_mut(),
        });
        let new_node_ptr: *mut Node<T> = &mut *new_node;
        if self.tail.is_null() {
            self.head = new_node_ptr;
        } else {
            new_node.next = self.tail;
            unsafe {
                (*self.tail).prev = new_node_ptr;
            }
        }
        self.tail = new_node_ptr;
    }
    pub fn remove_tail(&mut self) -> Option<T> {
        if self.tail.is_null() {
            None
        } else {
            let old_tail_ptr = self.tail;
            unsafe {
                if (*old_tail_ptr).next.is_null() {
                    self.tail = ptr::null_mut();
                    self.head = ptr::null_mut();
                } else {
                    let new_tail_ptr = (*old_tail_ptr).next;
                    (*old_tail_ptr).next = ptr::null_mut();
                    (*new_tail_ptr).prev = ptr::null_mut();
                    self.tail = new_tail_ptr;
                }
                (*old_tail_ptr).data.take()
            }
        }
    }
}

我的测试添加了十个整数 0..9然后他们弹出它们。在第二次弹出时,我得到

signal: 11, SIGSEGV: invalid memory reference.

最佳答案

以下将修复错误。在 add_tail :

  • 替换let new_node_ptr: *mut Node<T> = &mut *new_node;let new_node_ptr = Box::into_raw(new_node);
  • 替换new_node.next = self.tail(*new_node_ptr).next = self.tail;
  • 包括(*new_node_ptr).next = self.tail;unsafe阻止

错误是由于错误地从 Box 中获取了底层指针。

let new_node_ptr: *mut Node<T> = &mut *new_node; 之后Box 继续管理 new_node_ptr 指向的内存.在 block 的末尾,Box 自动释放内存,留下 new_node_ptr。悬空。

要通过手动内存管理获取指针并从 Box 释放内存控制,请使用 Box::into_raw而不是 &mut * .

关于list - 如何在这个简单的双向链表实现中修复 SIGSEGV?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55679855/

相关文章:

c# - 以列表为参数的重载函数

python - Python 子列表的时间复杂度

c++ - 调用 get 后将 shared_ptr 分配给另一个

java - 在Java中为单链表创建新节点

c++ - C++中如何删除链表的第一个节点

c++ - 从原始指针创建 shared_ptr 的链表

java - 获取 Set 中所有被拒绝的添加

编写循环的 Pythonic 方式

c++ - 使用指针从 std::list 中删除项目

c - 如何使用 C 中指向此数组的指针获取数组的大小?