es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿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:

  1. Mover todo dentro de parse_files a main, solo para encontrar un error de soltado de variables temporales.
  2. 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>
Tags:  , ,

Answer

  1. Avatar for 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 los Elf analizados a un nuevo vector. De esta manera, la duración de la porción de bytes creada por fs::read estará ligada a la duración del programa. Aquí tienes una implementación de ejemplo:

    fn parse_files(files: &[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())?);
        }
    
        Ok(elfs)
    }
    
    fn main() {
        let files = vec![String::from("foo"), String::from("bar")];
        let elfs = parse_files(&files).unwrap();
        // Haz algo con los elfs analizados...
    }
    

    Ten en cuenta que ahora se declara files con la macro vec![] en lugar de vec![].to_string(), para que contenga Strings en lugar de &strs. 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 un Vec<string>, y pasamos una referencia a files con &files. Esto hace que parse_files tome prestado el vector en lugar de tomar posesión de él, por lo que todavía podemos usarlo en main después de llamar a parse_files.

    Por último, el tipo de retorno de parse_files es Result<><elf<'static>>, Box<dyn error="">>, donde Elf<'static> significa que los objetos Elf devueltos tienen una duración estática (es decir, pueden sobrevivir al ámbito de parse_files). Esto es posible porque estamos creando un nuevo Vec para contener los Elf analizados, que los posee y tiene una duración estática.</elf<‘static></elf<‘static>

Comments are closed.