Rust

The memory safe and efficient language of the future

@Manishearth

C++ problems

  • Dangling pointers
  • Iterator invalidation
  • Thread safety

Dangling pointers



int* abc() {
	int x = 1;
	return &x;
}
	

Iterator invalidation



// Create the vector
vector<int> x;
x.push_back(1);
x.push_back(2);
x.push_back(3);

// Get an iterator
vector<int>::iterator itr = x.begin();

int j=0;
for (itr; itr !=x.end(); itr++) {
	x.push_back(j); // Uh oh!
	j++;
	cout << j << " .. ";
}
	

From a Stack Overflow question, by user620189

Why is this a problem?

  • SEGFAULT, SEGFAULT, SEGFAULT (Or: runtime failures are bad)
  • Extremely common source of security bugs in browsers and similar applications
  • Existing solutions for safety are slow and usually require a separate runtime with a GC

Existing solutions

  • Java: Garbage collection
  • Python, Ruby, etc: Interpreted languages, no need
  • C++11: Owned "smart" pointers

Memory management!

The good stuff

Moves and copies


let x = 5i;
let y = x;
println!("x is {}", x) // y was copied from x

let x = vec![1u, 2u, 3u]; // A vector
let y = x; // the vector was "moved"
println!("y is {}", y)
// Will not work, the vector is "owned" by y
// println!("x is {}", x)

fn abc(x: Vec<uint>) {
	// do something
}
let myvec = vec![1u, 2u, 3u];
abc(myvec); // myvec moved into function, cannot be used after this
	

Borrowing


let x = vec![1u, 2u, 3u];
let y = &x; // the vector was "borrowed"
let c = x.clone(); // Explicit copy
println!("x is {}", x)
println!("y is {}", *y)

fn abc(x: &Vec<uint>) {
	// do something
}
let myvec = vec![1u,2u,3u];
abc(myvec); // Passes a borrowed reference
// Still can use mybox here
	

Borrowing and mutability


let mut x = vec![1u,2u,3u];
{
  let y = &x; // the pointer was "borrowed"
  // x.push(1); // Not allowed, x is currently borrowed and cannot be mutated
  // y.push(1); // Not allowed, y is not a mutable reference
}
x.push(1) // The borrow was "returned", we can mutate now

let mut x = vec![1u,2u,3u];
{
  let y = &mut x; // the pointer was "borrowed", mutably
  // x.push(1); // Still not allowed, x is currently borrowed and cannot be mutated
  // println!("x is {}", x) // also not allowed, y is mutating this
  y.push(1); // Allowed, y is a mutable reference
}
x.push(1) // The borrow was "returned", we can mutate now
	

The heap


let mut x = box 1u; // On the heap
*x = 2;

// Type Box<uint>
// Also gets moved, not copied

fn abc() -> Box<int> {
	let x = box 1; // malloc() happened
	// do stuff with x or *x
	// free() happened
}
	

Unsafe


extern crate core;
use std::mem;
use core::ptr;
fn main() {
 let y = *dangle() + 1;
 // Segfault.
}

fn dangle() -> Box<int> {
 unsafe {
  // Null pointers!
  let mut p: *mut int = ptr::mut_null();
  let b = box 1; // Heap memory, will be deallocated at the end of this function
  ptr::write(p, *b);
  mem::transmute(p) // Converts to box and .. uh oh .. returns!
 }
}