Better living through abstraction

While not much short of hand crafted assembly will provide better performance than well written C there are many downsides to being able to do literally whatever you want to memory. The concept of an owning scope, and the ability of a scope to take ownership of some data is a good way to manage where variables are freed. While concepts of ownership are applied in existing languages such as C++, Rust , a recently released systems programming language developed by the Mozilla foundation uses it to create 100% memory safe code. Unlike languages that employ garbage collection Rust’s compiler uses ownership semantics to ensure that Rust code is memory safe. This technique creates memory safe code without the overhead of a complex language run-time. This does come at the cost of fighting the borrow checker, the component of the rust compiler that ensures ownership rules are followed. To understand why this can be helpful the piece of code below can be helpful

fn stack_return() -> &int {
    let i = 1234;
    return &i;
}

This code will not compile because the variable i is stack allocated, going out of scope at the end of the function. Since the function returns the borrowed pointer &i which has an owner whose lifetime is potentially longer than stack_return() this code will fail to compile because this creates a potential for an invalid memory access. By associating each piece of memory with an owner who can then lend it to other scopes rust is able to provide powerful guarantees about object lifetime and access. These impose certain restrictions on the language. For example the following code will not compile

fn main() {
    let mut x = vec!["Hello", "world"];

    let y = &x[0];

    x.push("foo");
}

The code above will fail to compile. While the vector is marked as mutable the line x.push(“foo”); is invalid. This is because push() requires a mutable reference to our vector x. This is because y is an immutable reference. As long as y is alive, there can be no mutable reference to x as it could potentially invalidate the data in y. Though typical rust code guarantees safety, it is possible to write potentially unsafe code using the unsafe{} directive, a necessary aspect of interfacing Rust with C, and other unsafe languages.

While semantics like this may seem over-complicated they completely eliminate an entire class of error without the cost of garbage collection. They also allow rust to make promises about data races that make writing concurrent code a much more manageable process than in classic systems languages. Rust also has many of the higher level features found in languages like C++ and Ocaml such as type traits, iterators, and RAII. while it’s performance is still not quite as good as that of C, Rust is rapidly becoming a viable, and reasonable, choice for several classes of problems. Additionally Rust’s compiler is based on LLVM providing excellent cross compilation and optimization capabilities.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s