Random segmentation fault with Vec<Option<NonNull<Node<T>>>>,

#1

The structs:

#[derive(Debug)]
pub struct Node<T> {
    data: Option<T>,
    forward: Vec<Option<NonNull<Node<T>>>>,
}

impl<T> Node<T> {
    fn new(data: T, level: usize) -> Self {
        Node {
            data: Some(data),
            forward: iter::repeat(None).take(level).collect(),
        }
    }
}
pub struct List<T> {
    head: Box<Node<T>>,
}

Part of insertion implementation:

let mut const_ptr: *const Node<T> = self.head.as_ref();
let mut height = self.get_max_height() - 1;
let next_ptr: *mut Node<T> = match (*const_ptr).forward[height] {
    None => { null_mut() }
    Some(mut v) => {
        println!("--- {:?} {:?}",v,(*v.as_ptr()).forward);
        v.as_ptr()
    }
};

I’m trying to use Option<NonNull<Node>> to implement a list structure, the above code is part of my implementation, my code throws segmentation fault exceptions, so I print the forward pointer vector, and I found that its output wasn’t always None as I wanted, more often it’s an undefined address e.g.:

--- 0x7ffeef8ef030 [Some(0x5000000000000000), Some(0x5000000000000000)]

But occasionally it’s None, and my code will work well:

--- 0x7ffee527d030 [None, None]

The inserted data is all the same, but my code produces different results.

So could someone point out where I’m using it wrong?

Any help would be greatly appreciated.

#2

You’re using unsafe, so the whole module matters. It will be very difficult to provide assistance without a playground example demonstrating the problem

4 Likes
#3

I’m trying to provide a simple example.

#4

And if I adjust the Node struct to this, replace the vector to slice, it works well

#[derive(Debug)]
pub struct Node<T> {
    data: Option<T>,
    forward: [Option<NonNull<Node<T>>>;K_MAX_HEIGHT]
}
#5

Don’t use unsafe :slight_smile:

3 Likes
#6

I did try, but I need these features like NonNull.

#7

No you don’t. https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.new Well yes, you need to dereference it, sorry!

Just don’t use NonNull then, use a Box instead

#8

Is NonNull a bit more optimized?

#9

Why would you think so? It shouldn’t

#10

What do you recommend to replae Vec<Option<NonNull<Node<T>>>>?

#11

Vec<Option<Box<Node<T>>>>

#12

Got it, I’m going to try it, thanks.

1 Like