【发布时间】:2021-08-05 14:30:02
【问题描述】:
最近我一直在尝试开发游戏 Super Star Trek 的 Rust 版本。但是,我在加载已保存的游戏时遇到了一个小问题。
要加载游戏,我将保存文件读入字符串,将其拆分为 Vec (以 \0x1e 作为分隔符),然后在两个结果元素上使用 serde_json::from_str 以获取我的游戏数据对象(一个用于 Enterprise,另一个用于 Universe)。
不幸的是,当我尝试退货时,我收到以下错误:
57 | return Some((ent, uni))
| ^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
据我所知,这是因为来自 .split.collect() 的数据被称为“临时”。
如何才能返回结构体?
编辑:这里是 github 仓库:https://github.com/thescribe11/Rust-SST
我的代码:
use crate::structs::{Enterprise, Universe};
use std::fs::{File};
use std::io::{Read, Write, stdin, stdout};
use serde_json::{to_string, from_str};
<snip>
pub fn get_config_from_file<'a> () -> Option<(Enterprise, Universe<'a>)>{
//! Thaw a game.
//!
//! The .sst file type is as follows:
//! <json data for Enterprise object>\0x1e<json data for Universe object>
let mut save_file: File;
loop {
let temp = File::open(input("Save file: "));
match temp {
Ok(p) => {save_file = p; break;},
Err(e) => {println!("Unable to find save file.\n"); continue;}
};
}
let pass = input("Password: ");
let mut enc_data = String::new();
match save_file.read_to_string(&mut enc_data) {
Ok(_) => {},
Err(_) => {println!("\nERROR: The save file is corrupted."); return None}
}
let mut ent: Enterprise; let mut uni: Universe;
let raw_parts: Vec<&str> = enc_data.split("\0x1e").collect();
ent = match serde_json::from_str(raw_parts[0]) {
Ok(data) => {data},
Err(_) => {println!("\nERROR: The save file is corrupted."); return None}
};
uni = match serde_json::from_str(raw_parts[1]) {
Ok(data) => data,
Err(_) => {println!("\nERROR: The save file is corrupted."); return None}
};
return Some((ent, uni))
}
【问题讨论】:
-
您的示例应用程序无法编译,但从错误消息来看,我猜您的
ent或uni变量包含对局部变量的引用。当函数返回时,该局部变量将不再存在,因此引用将指向已释放的内存。生锈可以防止这种非法行为。 -
您的
uni似乎包含一些引用,可能是&str,它指向raw_parts[1]的一部分。raw_parts在get_config_from_file末尾超出范围,所以uni不能活得更长。但是,您要退回它,所以它会比这更长寿。 Rust 禁止这样做。最简单的解决方案:将&str更改为字符串。 -
@sk_pleasant-EliasHolzmann 唉,那个解决方案不起作用。
-
对我有用。我正在写一个包含更多细节的答案。
-
您的
Universe<'a>持有对其解析的数据的引用,根据生命周期注释的存在来判断。如果没有源字符串,您将无法拥有它。