Closed lauti7 closed 1 year ago
For a Vec, We should not only dealloc the buffer, but also execute the drop
function of each element. This is just because each element may frees other resource(e.g. memory, socket, Rc
) in their drop
function.
@Rianico Thx for your quick response! Okay but the dealloc
doesn't work as a drop for each element? Or the drop
function is not executed when you dealloc the buffer?
Or the drop function is not executed when you dealloc the buffer.
Yes, dealloc
only free the memory, but won't execute the drop
function.
For example:
use std::alloc::{self, Layout};
struct MyStruct {
resource: u8,
}
impl Drop for MyStruct {
fn drop(&mut self) {
println!("free MyStruct's other resource: {}", self.resource);
}
}
fn main() {
let element1 = MyStruct { resource: 1 };
let buffer = Box::into_raw(Box::new(element1));
unsafe {
alloc::dealloc(buffer as *mut u8, Layout::new::<MyStruct>());
}
let _element2 = MyStruct { resource: 2 };
}
which will just print as below:
free MyStruct's other resource: 2
@Rianico Ok, perfect, got it! One doubt that I have now is when a custom struct like your MyStruct
is dropped, Is the memory automatically freed (dealloc
) or how is this handled in the compiler?
Thx for your help!
MyStruct
is a on-stack value, it's dropped as the stack frame popped. We don't need to handle it manually. And for Vec
, it allocates a sequence of memory on the heap, so we need to dealloc
it in the drop
function.
But that's not the point, the more imporant point can be found in 6. Ownership Based Resource Management
However we are not limited to just memory. Pretty much every other system resource like a thread, file, or socket is exposed through this kind of API.
So why we need to execute drop
function for each element? Beacuse drop
function of each element may free their own resources:
let ele1 = Vec[fd1, fd2];
let ele2 = Vec[fd3, fd4];
let v = Vec[ele1, ele2];
If we only dealloc
v
's buffer, the [fd1, fd2]
and [fd3, fd4]
won't be freed.
In the most case, Rust will recursively try to drop all of the fields of a struct. It's generated by the the compiler, which is super convenient, right? You can recap the 6.2. Destructors to get more details.
But in Vec
, we use the raw pointer, and the compiler don't know how to free it. So we need to implement drop
function to free its memory manually(dealloc
), and other resource(call the drop
of each element).
@Rianico Amazing, so good explanation! I'll see those links. Thx for your help
In chapter 9.7 on the Nomicon, when the trait
Drop
is implemented a for-loop on&mut self
is executed with a comment saying// drop any remaining elements
. Why is this for-loop needed? Because after this for-loop, the buffer itself is deallocated. What is the difference between both? I thought that it was enough with thealloc::dealloc
function.Hope you can help with this doubt! Thx in advance.
The code below: