An example from the nomicon book

I played with Destructors - The Rustonomicon

#![feature(allocator_api, ptr_internals)]

use std::alloc::{Allocator, GlobalAlloc, Global, Layout};
use std::ptr::{drop_in_place, Unique, NonNull};
use std::mem;

struct Box<T>{ ptr: Unique<T> }

impl<T> Drop for Box<T> {
    fn drop(&mut self) {
        println!("drop for box");
        unsafe {
            drop_in_place(self.ptr.as_ptr());
            let c: NonNull<T> = self.ptr.into();
            Global.deallocate(c.cast(), Layout::new::<T>());
        }
    }
}

struct SuperBox<T> { my_box: Option<Box<T>> }

impl<T> Drop for SuperBox<T> {
    fn drop(&mut self) {
        unsafe {
            println!("drop for superbox");
            // Hyper-optimized: deallocate the box's contents for it
            // without `drop`ing the contents. Need to set the `box`
            // field as `None` to prevent Rust from trying to Drop it.
            let my_box = self.my_box.take().unwrap();
            let c: NonNull<T> = my_box.ptr.into();
            println!("dealloc before");
            Global.deallocate(c.cast(), Layout::new::<T>());
            println!("dealloc after");
            mem::forget(my_box);
            println!("drop for superbox end")
        }
    }
}

struct MyStruct {
    value: String
}

impl Drop for MyStruct {
    fn drop(&mut self) {
        println!("my struct with {} is dropped", self.value)
    }
}


#[cfg(test)]
mod tests {
    use crate::{MyStruct, SuperBox, Box};
    use std::ptr::{Unique};

    #[test]
    fn it_works() {
        let mut my_struct = MyStruct {value: String::from("hello")};
        let my_box = SuperBox {
            my_box: Some(Box {ptr: Unique::new(&mut my_struct).unwrap()})
        };
    }
}

But the compiler say: pointer being freed was not allocated

the full print:

drop for superbox
dealloc before
leetcode-41858686c677d18c(13921,0x700002f08000) malloc: *** error for object 0x700002f078b8: pointer being freed was not allocated
leetcode-41858686c677d18c(13921,0x700002f08000) malloc: *** set a breakpoint in malloc_error_break to debug

You're just creating a pointer to something on the stack here. No wonder it complains if you're trying tok deallocate this with the global allocator - after all, it was never allocated with the global allocator. :wink:

1 Like

So could you give an example of this :grinning:

Oh I found it right now:

fn it_works() {
    let my_struct = MyStruct {value: String::from("hello")};
    let mut box_my_struct = std::boxed::Box::new(my_struct);
    let my_box = SuperBox {
        my_box: Some(Box {ptr: Unique::new(box_my_struct.as_mut()).unwrap()})
    };
    std::mem::forget(box_my_struct);
}

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.