Rust memory management: Difference between revisions

From wikinotes
Line 28: Line 28:


== Ownership ==
== Ownership ==
<blockquote>
=== Copy Trait ===
<blockquote>
<blockquote>
* Objects have a single owner at once
* Objects have a single owner at once
Line 49: Line 51:
}
}
</syntaxhighlight>
</syntaxhighlight>
</blockquote><!-- Copy Trait -->


=== References ===
<blockquote>
Passing references enables passing objects to arguments without transferring ownership.<br>
Passing references enables passing objects to arguments without transferring ownership.<br>
However:
However:
Line 65: Line 70:
}
}
</syntaxhighlight>
</syntaxhighlight>
In rust, because of lifetime semantics, you can't return a reference from an object created in a function.<br>
You need to return the object itself, so that it's ownership is transferred.
<syntaxhighlight lang="rust">
// INVALID!
fn foo() -> &String {
    let s = String::from("hi");
    &s
}
// VALID
fn foo() -> String {
    let s = String::from("hi");
    s
}
</syntaxhighlight>
</blockquote><!-- References -->
</blockquote><!-- Ownership -->
</blockquote><!-- Ownership -->
</blockquote><!-- General -->
</blockquote><!-- General -->

Revision as of 17:33, 7 February 2023

Rust uses ownership semantics for memory management.

Documentation

official tutorial https://doc.rust-lang.org/stable/book/ch04-00-understanding-ownership.html

General

Stack

The stack is

  • a LIFO
  • push=add, pop=remove (from the top)
  • only supports fixed-size datatypes
  • fast

Heap

  • access provided through pointers (a fixed-size, usable on stack)
  • slower

Ownership

Copy Trait

  • Objects have a single owner at once
  • When owner goes out of scope, value is dropped (with drop())
  • When an object is passed as a function-parameter, that function now owns it (and it cannot be referenced in current context).

See example of ownership in action.

fn print_i32(i: i32)    { println!("{}", i); }
fn print_str(s: String) { println!("{}", s); }

fn main() {
    let i = 123;
    print_i32(i);       // `i` has `Copy` trait, `foo` gets a shallow copy
    println!("{}", i);  // valid! `i` is still owned by `main()`

    let s = String::from("abc");
    print_str(s);       // `s` does not have `Copy` trait, pointer passed to function, which now owns it
    println!("{}", s);  // <-- BANG! not allowed to use `s` anymore
}

References

Passing references enables passing objects to arguments without transferring ownership.
However:

  • only a single mutable reference can exist for the same object at a time.
  • if a mutable reference for an object exists, there cannot be immutable references to that object

I'm thinking of this as a read/write lock (multiple readers allowed, nobody can read/write while writing).

fn print_str(s: &String) { println!("{}", s); }

fn main() {
    let s = String::from("abc");
    print_str(&s);
    println!("{}", s);  // <<-- valid! `main` still owns the object
}

In rust, because of lifetime semantics, you can't return a reference from an object created in a function.
You need to return the object itself, so that it's ownership is transferred.

// INVALID!
fn foo() -> &String {
    let s = String::from("hi");
    &s
}

// VALID
fn foo() -> String {
    let s = String::from("hi");
    s
}