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.

El puntero al primer elemento del vector en Result<>, _> está corrompido.

Tengo un Result<><f64>, _>. Cuando intento extraer un puntero al arreglo real de f64, lo que observo es que el arreglo al que apunta dptr es una versión corrupta del arreglo esperado (los primeros 10 bytes han sido cambiados).

¿Por qué ocurre esto y cómo puedo evitarlo?

use std::error::Error;

fn main() {
    let res: Result<><f64>, Box<dyn error="">> = Ok(vec![1., 2., 3., 4.]);
    let dptr: *const f64 = match res {
        Ok(v) => &v[0], 
        Err(_) => std::ptr::null(),
    };
    assert_eq!(unsafe { *dptr }, 1.0);
}

Resultado:

thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `0.0`,
 right: `1.0'`, src/main.rs:9:5

Playground

Tags:  , ,

Answer

  1. Avatar for davy.ai

    La razón por la cual esto ocurre es porque el Vec es descartado al final de la declaración match, lo cual significa que el puntero dptr está apuntando a una memoria inválida. Cuando se llama a la macro assert_eq!, se verifica el valor en la ubicación de memoria señalada por dptr, la cual ahora contiene datos basura.

    Para evitar este problema, puedes utilizar Box::into_raw para convertir el Vec en un puntero sin restricciones que puedas administrar explícitamente. Aquí tienes un ejemplo:

    use std::error::Error;
    
    fn main() {
        let res: Result<><f64>, Box<dyn error="">> = Ok(vec![1., 2., 3., 4.]);
        let mut v = match res {
            Ok(v) => v,
            Err(_) => return,
        };
    
        let dptr: *const f64 = v.as_ptr();
        std::mem::forget(v); // Evita que el Vec se descarte
    
        assert_eq!(unsafe { *dptr }, 1.0);
        // ... Realiza operaciones con el puntero sin restricciones ...
        // No olvides liberar la memoria cuando hayas terminado:
        // let _ = Box::from_raw(dptr);
    }
    

    En este ejemplo, utilizamos v.as_ptr() para obtener un puntero sin restricciones al primer elemento del Vec. Luego, llamamos a std::mem::forget(v) para evitar que el Vec sea descartado cuando sale del ámbito. Esto nos permite utilizar el puntero sin restricciones de manera segura fuera de la declaración match.

    Ten en cuenta que si vas a asignar memoria o manipular el puntero de alguna forma, debes liberar correctamente la memoria cuando hayas terminado utilizando Box::from_raw(dptr), para evitar fugas de memoria.

Comments are closed.