Rust反序列化元组元素时的生命周期错误问题排查
反序列化元组值时的生命周期错误原因分析
问题场景与代码
尝试反序列化元组内的值并推入数组时触发生命周期错误,原代码如下:
fn main() { let raw_value = vec![(1, ("a", "a", 1))]; // 序列化 let mut serialized_value = vec![]; for val in raw_value.iter() { serialized_value.push(( bincode::serialize(&val.0).unwrap(), bincode::serialize(&val.1).unwrap(), )); } // 反序列化 let mut deserialized_value: Vec<(&str, &str, i32)> = vec![]; for val in serialized_value { deserialized_value.push(bincode::deserialize(&val.1).unwrap()); } }
运行后出现的错误:
error[E0597]: `val.1` does not live long enough --> src/main.rs:18:54 | 18 | deserialized_value.push(bincode::deserialize(&val.1).unwrap()); | ---------------------------------------------^^^^^^----------- | | | | | borrowed value does not live long enough | borrow later used here 19 | } | - `val.1` dropped here while still borrowed
错误原因
核心是Rust的生命周期规则限制:
bincode反序列化&str时,默认不会分配新内存,而是直接从输入的字节切片(即val.1)中借用数据,生成的引用和原字节切片的生命周期绑定。- 循环中,
val是从serialized_value中移出的元素,每次循环结束后,val会被Rust自动销毁,其包含的val.1字节切片也会被释放。 - 但你把反序列化得到的
(&str, &str, i32)存入了deserialized_value,这个向量的生命周期远长于循环中的val,相当于试图保存指向已销毁内存的引用,直接违反了Rust的内存安全原则,因此编译器报错。
重构后可行的原因
如果把 val.1 从元组中移出重构,本质上是解决了生命周期不匹配的问题:
- 要么让反序列化的输入数据(字节切片)拥有更长的生命周期,避免在循环结束后被销毁;
- 更常用的方案是将
deserialized_value的类型改为Vec<(String, String, i32)>,此时bincode会把字节数据反序列化为拥有所有权的String,不再依赖原字节切片的生命周期,自然不会触发生命周期错误。
内容的提问来源于stack exchange,提问作者Fast Eater
相关产品推荐
相关产品推荐

