¿Cómo puedo usar Elf::parse de Goblin con una variable temporal?
Estoy intentando iterar sobre una serie de nombres de archivo y analizar los archivos correspondientes.
Mi Cargo.toml
:
[package]
name = "fold"
version = "0.1.0"
authors = ["Akshat Mahajan"]
edition = "2018"
: See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
goblin = "0.4.3"
Mi main.rs
:
/// Un enlazador de programas para generar ejecutables ELF de x64 a partir de archivos objeto.
use goblin::elf::Elf;
use std::error::Error;
use std::fs;
fn parse_files(files: Vec<string>) -> Result<><elf<'static>>, Box<dyn error="">> {
let mut elfs: Vec<elf> = vec![];
for file in files {
elfs.push(Elf::parse(fs::read(file)?.as_slice())?);
}
return Ok(elfs);
}
fn main() {
parse_files(vec!["foo".to_string(), "bar".to_string()]);
}
El comprobador de préstamos genera un error:
none
error[E0515]: no se puede devolver un valor que hace referencia a un valor temporal
--> src/main.rs:17:12
|
14 | elfs.push(Elf::parse(fs::read(file)?.as_slice())?);
| --------------- valor temporal creado aquí
...
17 | return Ok(elfs);
| ^^^^^^^^ retorna un valor que hace referencia a datos propiedad de la función actual
Elf::parse
solo acepta una matriz de bytes en lugar de cualquier cosa asignada en el montón para una vida útil más larga:
pub fn parse(bytes: &'a [u8]) -> Result<self>
¿Cuál es la forma correcta de hacer que esta operación tenga éxito?
Cosas que he intentado:
- Mover todo dentro de
parse_files
amain
, solo para encontrar un error de soltado de variables temporales. - Leer https://stackoverflow.com/questions/32682876/is-there-any-way-to-return-a-reference-to-a-variable-created-in-a-function. No creo que esto me ayude porque parece que mi problema real es que la vida útil del flujo de bytes creado por
fs::read
es temporal, cuando realmente quiero que esté vinculado a la vida útil del programa. No sé cómo lograr esto de manera limpia.</elf<‘static>
davy.ai
Para que esta operación tenga éxito, debes pasar una referencia al vector de archivos a
parse_files
, en lugar del vector en sí mismo. Luego, puedes iterar sobre la referencia y agregar losElf
analizados a un nuevo vector. De esta manera, la duración de la porción de bytes creada porfs::read
estará ligada a la duración del programa. Aquí tienes una implementación de ejemplo:Ten en cuenta que ahora se declara
files
con la macrovec![]
en lugar devec![].to_string()
, para que contengaString
s en lugar de&str
s. Esto nos permite tomar una referencia al vector en lugar de un valor propio.Además,
parse_files
ahora toma un slice&[String]
en lugar de unVec<string>
, y pasamos una referencia afiles
con&files
. Esto hace queparse_files
tome prestado el vector en lugar de tomar posesión de él, por lo que todavía podemos usarlo enmain
después de llamar aparse_files
.Por último, el tipo de retorno de
parse_files
esResult<><elf<'static>>, Box<dyn error="">>
, dondeElf<'static>
significa que los objetosElf
devueltos tienen una duración estática (es decir, pueden sobrevivir al ámbito deparse_files
). Esto es posible porque estamos creando un nuevoVec
para contener losElf
analizados, que los posee y tiene una duración estática.</elf<‘static></elf<‘static>