Bienvenidos sean a este post, hoy veremos una forma particular de manejar la ubicacion en memoria.
Hasta ahora hemos hablado sobre la partes de la memoria llamadas stack y heap, pero hoy hablaremos sobre una forma muy particular de ubicacion de memoria como es la llamada estatica, esta no es ubicada al momento de ejecucion pero la mueven dentro de la memoria con el codigo del programa antes de que este sea ejecutado, un par de ejemplos que se pueden ubicar en esta seccion de memoria son static y const y esta existira mientras exista la aplicacion.
En muchos lenguajes hoy tenemos algo conocido como Recolector de basuras (Garbage Collector), este se encarga basicamente de monitorear la memoria heap, verificar cuales son los elementos que no son usados o estan asignados a algun objeto y procede a eliminarlos de la memoria, en Rust tenemos uno muy primitivo en forma de un contenedor contado de referencia, Rc<T>, pero por lo general no es necesario utilizarlo dado que es un proceso que es preferible que se encargue el sistema.
Hasta el momento hemos visto que una variable comun se almacena en el stack, los objetos se ubican en el heap, a su vez nosotros podemos crear variables que apunten a estos objetos, tambien podemos tener la cantidad que queramos de variables que apunten a estos objetos, e inclusive copias de estos apuntadores, siempre liberaremos el original pero esto puede caer en serios problemas de memoria, pero recordemos que Rust libera de forma automatica de la memoria todos las expresiones que se fueron de su rango, evitando algunos de los inconvenientes que ocurren en otros lenguajes.
Basta de tanta teoria, vamos a ver un poco de practica, para ello revisitaremos un codigo que vimos en este post, en ese caso creamos un proyecto llamado ejemplo01 y dentro de main.rs agregamos el siguiente codigo final:
main.rs
fn main() {
let x = 5u32;
let y =
{
let x_cuadrado = x * x;
let x_cubo = x_cuadrado * x;
x_cubo + x_cuadrado + x
};
let z =
{
2 * x
};
println!("x es {:?}", x);
println!("y es {:?}", y);
println!("z es {:?}", z);
}
En este caso lo usamos para explicar el uso del punto y coma en un bloque, si quieren saber realmente como trabaja les recomiendo visitar el post pero en resumidas cuenta se ven como asignar los valores para tres variables y luego mostrarlas, si lo compilamos y probamos funcionara perfectamente sin ningun error pero ahora tomemos el bloque donde definimos a la variable y para modificarlo de la siguiente forma:
let y: &u32;
{
let x_cuadrado = x * x;
let x_cubo = x_cuadrado * x;
y = &(x_cubo + x_cuadrado + x);
};
En este caso lo modificamos para establecer el tipo que recibira y asi como tambien lo creamos para que se almacene la informacion en el heap en lugar del stack, luego volvemos a repetir la creacion de las dos variables como en el bloque anterior, la unica diferencia es que la operacion final se la asignamos a la variable y, por ultimo modificaremos esta linea:
println!("y es {:?}", y);
De la siguiente forma:
println!("y es {:?}", *y);
Para que busque el valor en la direccion de memoria donde esta el apuntador, antes de compilarlo veamos su codigo final:
main.rs
fn main() {
let x = 5u32;
let y: &u32;
{
let x_cuadrado = x * x;
let x_cubo = x_cuadrado * x;
y = &(x_cubo + x_cuadrado + x);
};
let z =
{
2 * x;
};
println!("x es {:?}", x);
println!("y es {:?}", *y);
println!("z es {:?}", z);
}
Con todo comentado procedamos a compilarlo y veamos su salida:
tinchicus@dbn001vrt:~/lenguajes/rust/ejemplo01$ cargo build
Compiling ejemplo01 v0.1.0 (/home/tinchicus/lenguajes/rust/ejemplo01)
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:8:8
|
8 | y = &(x_cubo + x_cuadrado + x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
...
17 | println!("y es {:?}", *y);
| -- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
For more information about this error, try `rustc --explain E0716`.
error: could not compile `ejemplo01` due to previous error
tinchicus@dbn001vrt:~/lenguajes/rust/ejemplo01$
Observen que nos devolvio un error y no se compilo, esto es debido a que el compilador en general verifica las posibles conductas de sus variables, en este caso observa que toma la conducta que mencionamos en otros casos, es decir que se sale del rango dado que una vez terminado el bloque el valor pasado a y se borrara de la memoria, y el error lo tendremos al momento de mostrarlo porque ira a una direccion de memoria que no existe, observen que nos sugiere que en lugar de asignarlo a una variable externa usemos el let para que quede todo en el bloque, tengan en cuenta esto y siempre observen las sugerencias que nos devuelve el compilador.
En resumen, hoy hemos visto como es la memoria estatica, caracteristicas de esta, cual es su forma de trabajar, vimos un pequeño ejemplo de como se borra un dato de la memoria cuando se sale de su rango, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.50
