Muisti ja lainaus


Omistajuuden säännöt

  • Jokaisella arvolla on tasan yksi omistaja tietyllä hetkellä
  • Kun omistaja poistuu skoopista, arvo pudotetaan eikä siihen pääse enää käsiksi

Kutsupino (stack)

  • Pino kehyksiä
  • Funktiokutsu työntää kehyksen kutsupinoon ylimmäksi
  • Funktion palautuessa ylin kehys tuhotaan
  • Kääntäjän pitää tietää kääntöaikana jokaisen kehyksen ja niille laitettavan tiedon koko

stack


Kutsupinon lautasmalli

lautasmalli

fn add(x: i32) {
	let y = 10;
}

fn main() {
	let x = 5;
	add(x); // <---
}

lautasmalli

fn add(x: i32) -> i32 {
	let y = 10;
	x + y // <---
}

fn main() {
	let x = 5;
	let z = add(x);
}

Tavut muistissa

u8, i8 u32, i32 u64, i64

Tavut muistissa

usize, isize Osoittimen kokoinen
(8 tavua 64-bittisellä prosessorilla)
*const T Osoitin ptr

Tyypit muistissa

T T Kääntöaikana
tunnettu koko
[T; n] T T T ... n Taulukko, joka sisältää
n elementtiä
[T] ... T T T ... Slice on jatkuva alue muistia ja koostuu
vain tyypin T ilmentymistä. Slicen koko
tiedetään aina ajonaikana

Keko (heap)

  • Dynaaminen muisti

  • Mahdollistaa vapaakokoisten tyyppien tallentamisen toisin kuin pinoon kehykselle

  • Hitaampi kuin stack, koska muisti pitää varata

  • Osa tietorakenteesta (kuten osoitin) sijaitsee aina stackilla

T T T T T T T T T T T T T
Vec<T> ptr capacity len |
T T ... len
capacity

Referenssi

&T ptr | T Pitää viitata validiin
ilmentymään Tstä

Use after free

#![allow(unused)]
fn main() {
let mut data = vec![1, 2, 3];
// get an internal reference
let x = &data[0];

// OH NO! `push` causes the backing storage
// slice of `data` to be reallocated.
// Dangling pointer! Use after free!
data.push(4);

println!("{}", x);
}

(Yleinen virhe C-ohjelmoinnissa)


#![allow(unused)]
fn main() {
error[E0502]: cannot borrow `data` as mutable
	because it is also borrowed as immutable
  --> src/main.rs:8:5
   |
4  |     let x = &data[0];
   |              ---- immutable borrow occurs here
...
8  |     data.push(4);
   |     ^^^^^^^^^^^^ mutable borrow occurs here
9  |
10 |     println!("{}", x);
   |                    - immutable borrow later used here
}

fn main() {
    let s1 = gives_ownership();
    let s2 = String::from("hello");
	
	// s2 is moved into takes_and_gives_back,
	// which also moves its return value into s3.
	// ... in a way s2 was borrowed
    let s3 = takes_and_gives_back(s2);
	// continue using the string ...
}

fn gives_ownership() -> String {
    let some_string = String::from("yours");

	// some_string is returned and
	// moves out to the calling function
    some_string
}

fn takes_and_gives_back(mut a_string: String) -> String {
	// do something with a_string ...
	
    a_string
}

Lainauksen säännöt

  • Jokaisella hetkellä ohjelman suorituksen aikana voi olla...
    • Mikä tahansa lukumäärä muuttumattomia lainauksia &T
    • Tai yksi muuttuva lainaus &mut T
  • Referenssien tulee aina osoittaa validiin Tn instanssiin


Otarustlings tauko


Referenssi sliceen

&[T] ptr len | [T] ... T T ... Slicet on olemassa vain referenssinä

String slice

&str ptr len | ... U T F - 8 ... String slice referenssi
len on pituus tavuina

Ohjelma

  • Konekielelle käännetyt käskyt (instructions)
  • Usein kutsunaan binääriksi
  • Ladataan muistiin, kun se suoritetaan

Prosessi

  • Luodaan ohjelman käynnistyessä
  • Omistaa oman muistialueen
  • Käyttöjärestelmä käynnistää prosessin
  • Prosessissa on aina vähintään yksi säie

htop


Säie

  • Suorittaa konekäskyjä itsenäisesti
  • Joka säikeellä on oma kutsupino
  • Prosessin säikeet jakavat kaikki muut resurssit

Lopuksi

idiomatic rust