【问题标题】:How to fix a SIGSEGV in this simple doubly linked list implementation?如何在这个简单的双向链表实现中修复 SIGSEGV?
【发布时间】:2019-04-14 20:41:14
【问题描述】:

运行此代码时出现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,然后它们弹出它们。在第二次弹出时,我得到 ​​p>

信号:11,SIGSEGV:无效的内存引用。

【问题讨论】:

  • let mut new_node = Box::new 将在drop 超出范围后分配Node,在let new_node_ptr: *mut Node&lt;T&gt; = &amp;mut *new_node; 中留下一个悬空指针。而且我不确定你为什么在这里使用不安全的代码
  • simple双向链表——如果你关心这些数据类型到底有多复杂,我发现你没有被正确地介绍过内存安全... (Learn Rust With Entirely Too Many Linked Lists)
  • “我的测试加了十个整数0..9那只有9个整数。

标签: list pointers linked-list rust unsafe


【解决方案1】:

以下将修复错误。在add_tail:

  • let new_node_ptr: *mut Node&lt;T&gt; = &amp;mut *new_node; 替换为let new_node_ptr = Box::into_raw(new_node);
  • new_node.next = self.tail 替换为(*new_node_ptr).next = self.tail;
  • unsafe 块中包含(*new_node_ptr).next = self.tail;

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

let new_node_ptr: *mut Node&lt;T&gt; = &amp;mut *new_node; 之后,Box 继续管理new_node_ptr 指向的内存。在块结束时,Box 自动释放内存,使 new_node_ptr 悬空。

要获得手动内存管理的指针并从 Box 释放内存控制,请使用 Box::into_raw 而不是 &amp;mut *

【讨论】:

  • “正确的解决方法”是根本不使用指针。使用Option&lt;Box&lt;_&gt;&gt; 的组合,您不需要任何原始指针。如果你真的想要它们,请使用Option&lt;NonNull&lt;_&gt;&gt; 来确定,你不能有空指针。
猜你喜欢
  • 2012-05-10
  • 2019-11-23
  • 1970-01-01
  • 2020-05-05
  • 2021-11-18
  • 2011-06-03
  • 2018-03-14
  • 2015-05-16
相关资源
最近更新 更多