Implementation of a stack for frames

Hello,

I'm trying to implement a stack to contain data of different types. This is what I did here but it doesn't work, a segmentation fault happens. I don't see what went wrong. Any hint?

Thanks.

I think you need to re-read the documentation of Vec::reserve.

In particular

-   if frame_len_by_usize > stack.capacity() {
-       stack.reserve(frame_len_by_usize - stack.capacity());
-   }
+   stack.reserve(frame_len_by_usize)

seems to be an improvement.

I don't quite understand what you meant to do here:

        let ptr = ptr.add(1) as *mut And;
        let mut vec = Vec::from_raw_parts(ptr, 0, num);

You cannot call Vec::from_raw_parts on an arbitrary pointer; it has to be one that you got by calling Vec::into_raw_parts (or Box::into_raw). Creating a Vec from ptr does not do anything useful and might be instant UB because you get it by adding sizeof<FrameHeader>() which is not necessarily aligned to usize.

I would also do some additional changes:

First add a bunch of repr for sanity:

#[repr(usize)]
enum Kind {
    And, Or
}

#[repr(C)]
struct FrameHeader {
    pub len: usize,
    pub kind: Kind,
    // Something
}

#[derive(Debug, Clone, Default)]
#[repr(C)]
struct And {
    pub a: usize,
    pub b: usize,
}

#[allow(dead_code)]
#[repr(C)]
struct Or {
    pub c: usize,
    pub d: usize,
    pub e: usize,
    pub f: usize,
}

so that we can be certain that the enum doesn’t create unitialized padding bytes and everything is aligned to usize.

Then, as @trentj mentioned, the Vec::from_raw_parts seems dodgy. There are better alternatives to this. For example you could use something like

let ptr = ptr.add(1) as *mut mem::MaybeUninit<And>;
let slice = slice::from_raw_parts_mut(ptr, num);
for slot in slice {
    *slot = mem::MaybeUninit::new(And { a: 1, b: 3 });
}
stack.set_len(stack.len() + frame_len_by_usize);
slice::from_raw_parts_mut(ptr as *mut And, num)

instead.

1 Like

Thanks you.

Also note that you can easily avoid all the unsafe code using the bytemuck crate.

(Well, at the cost of Kind no longer being an enum..)

There are many ways to implement this, I would like one where I delegate as much as possible to the compiler (unsafe isn't fun). I added your changes and with generic I have this.

Where could I find something similar to this idea?

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.