Reputation: 11
I get a SIGSEGV
error when running this code.
The code compiles, the debugger shows what looks like random addresses in pointers.
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()
}
}
}
}
My test adds ten integers 0..9
and them pops them. On second pop, I get
signal: 11, SIGSEGV: invalid memory reference.
Upvotes: 0
Views: 96
Reputation: 11
The following will fix the error. In add_tail
:
let new_node_ptr: *mut Node<T> = &mut *new_node;
with let new_node_ptr = Box::into_raw(new_node);
new_node.next = self.tail
with (*new_node_ptr).next = self.tail;
(*new_node_ptr).next = self.tail;
in the unsafe
blockThe error was due to obtaining the underlying pointer from the Box incorrectly.
After let new_node_ptr: *mut Node<T> = &mut *new_node;
the Box continued to manage the memory pointed to by new_node_ptr
. At the end of the block, the Box deallocated the memory automatically leaving new_node_ptr
dangling.
To obtain a pointer with manual memory management and to release control of memory from the Box, use Box::into_raw
instead of &mut *
.
Upvotes: 1