How does one deep copy properly from heap a dynamically sized trait objects?
I've been reading a lot for the past week and a half and I believe I'm still not understanding whether I've been close to solving my solution or whether I'm on the right path.
So I'm having the following actors in my scenario:
pub type CustomType = Box<dyn SomeTrait + Send + Sync + 'static>
// due to async trait impl Self is ?Sized
#[async_trait]
trait SomeTrait: Send {
async fn some_async_fn(&self) -> bool;
}
#[derive(Clone)]
struct SomeStruct {
vec_hold: Vec<CustomType>
}
I'm also having a function that should return an owned copy of this Vec<CustomType>
, therefore I have to impl Clone for CustomType {}
where I decided to try copy the values from heap memory into a new allocation and return the object.
What I tried so far was creating a new allocation with align_of_val(self)
and size_of_val(self)
then copy_nonoverlaping(self, dst, size_of_val(self))
and return ptr::read(dst)
, I've tried a dozen of different variants before realizing that write/read are attempting at moving memory unlike copy_nonoverlaping
(to the guys who wrote the documentation - thank you! your work is highly appreciated), after a while I've tried copying bytes into a Vec that would be casted to the object finally - couldn't figure out how to cast it, then finally I've decided to give a go with MaybeUninit
.
Results:
- In my best case scenarios the app crashes after (almost) 2 successful memory copies with heap corruption (undefined behavior probably due to improper cleanup after use of allocated memory, I've tried drop_in_place after use) (and I say almost 2 successful because the operation gets executed almost till the end and then suddenly crashes)
- In my worst case scenarios it crashes with access violation (that's when I know that I've really screwed up with playing with the raw pointers)
My research on the case:
I've found easily the solutions of people who easily bypass the problem by adding another step of cloning and also found a crate that does that for you, however these two are covering cases where Self: Sized while I need it for ?Sized.
Any explanation and idea is highly appreciated, also you are free to assume that I know nothing about memory management, because its true and I'm currently learning. I've been recently reading about memory alignment and size of types and how they reflect the alignment and about rust afinite memory management.