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