I want to understand how from_pointer will behave. What does that &'static
mean? Will the lifetime of the &'static T
outlive the scope?
It's unsafe anyway. The lifetime is set by the value that is given to to_pointer
. I just wanna know how it would behave if I would create a ton of references to the same item.
if I have something like this:
let pointer = to_pointer(&string);
for _ in 0..999999 {
let value = from_pointer(pointer);
println!("{value}")
}
will it cause a memory leak? is value disposed at the closing bracket or will this create a ton of refrences that are never disposed?
fn to_pointer<T>(value: &T) -> *const T {
value as *const T
}
fn from_pointer<T>(pointer: *const T) -> &'static T {
unsafe { &*pointer }
}
Same goes for this. What effect does the T: 'static
have. can it cause memory leaks? My guess would be that it is the same as from_pointer
pub struct Pointer<T>(*const T);
impl<T: 'static> Deref for Pointer<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.0 }
}
}
Gosh. There's a lot to unpack here.
What does that
&'static
mean? Will the lifetime of the&'static T
outlive the scope?
A reference with 'static
lifetime indicates that the referent lives for the remaining lifetime of the running program. That raw pointers do not carry a lifetime that the compiler can use to perform borrow-checking, and you are therefore capable of creating &'static
references from them, does not mean that doing so is correct or valid: it is up to you to ensure that the preconditions (in this case that the pointer will be valid for reads for the remaining lifetime of the running program) are satisfied.
will it cause a memory leak?
I think you are using the term "memory leak" incorrectly. A memory leak occurs when allocated memory is no longer reachable, but is not freed (this isn't usually desirable, as it is a waste of resources, but it is perfectly defined and acceptable behaviour in Rust). I think you may have instead meant to ask about "dangling pointers" which are almost the exact opposite: pointers to freed memory. It is Undefined Behaviour to have a reference to freed memory.
is value disposed at the closing bracket or will this create a ton of references that are never disposed?
value
is indeed dropped when to_pointer
returns; however, value
in this case is just a reference to T
. Dropping a reference does not drop the referent, so the T
will still be in its memory location after to_pointer
returns.
However, because your from_pointer
creates an &'static T
while the pointer is not guaranteed to remain valid for 'static
lifetime, it is not correct. A better version might look like this:
/// # Safety
/// `pointer` must be valid for shared reads for the `'a` lifetime
unsafe fn from_pointer<'a, T>(pointer: *const T) -> &'a T {
&*pointer
}
This way, calling from_pointer
is an unsafe operation, and callers are required to uphold the safety precondition.
What effect does the
T: 'static
have
T: 'static
constrains which types may instantiate the generic parameter to those that have only 'static
borrows (or longer, which doesn't exist). It does not guarantee that the pointer is valid, and therefore the implementation of Deref
is incorrect unless you are able to guarantee that a Pointer<T>
can only exist when its field is valid to read for shared access. Otherwise, a better version might look like this:
impl<T> Pointer<T> {
/// # Safety
/// The pointer must be valid for shared reads for the `'a` lifetime
unsafe deref<'a>(&self) -> &'a T {
&*self.0
}
}
This way and as before, responsibility for upholding the safety precondition is pushed onto the caller.