Reputation: 350
This example compiles and returns the "expected" output. But is this not a dangling pointer scenario? If so, how come the rust compiler allows this?
use serde_json::{Value, json};
use std::io::Result;
fn main(){
println!("{:#?}", test_json_lifetime());
}
fn test_json_lifetime() -> Result<(Value)> {
let j = json!({ "name" : "test" });
Ok(j)
}
Upvotes: 0
Views: 391
Reputation: 1455
It sounds like you are thinking that j
is allocated on the stack frame of test_json_lifetime()
(that memory gets deallocated at the end of the function when the stack unwinds), and we return a reference to j
(which would result in a dangling pointer).
In this case, you are correct that j
gets allocated on the stack, however when we return Ok(j)
we do not return a reference to j
, rather we copy j
to the space for the Result<(Value)>
that was allocated on main()
's stack frame before the function call to test_json_lifetime()
.
Upvotes: 1
Reputation: 350
I found the answer in this section.
fn main() {
let s1 = gives_ownership(); // gives_ownership moves its return
// value into s1
let s2 = String::from("hello"); // s2 comes into scope
let s3 = takes_and_gives_back(s2); // s2 is moved into
// takes_and_gives_back, which also
// moves its return value into s3
}
// Here, s3 goes out of scope and is dropped. s2 goes out of scope but was
// moved, so nothing happens. s1 goes out of scope and is dropped.
fn gives_ownership() -> String { // gives_ownership will move its
// return value into the function
// that calls it
let some_string = String::from("hello"); // some_string comes into scope
some_string // some_string is returned and
// moves out to the calling
// function
}
Upvotes: 0