DEV Community

Cover image for Learning Rust πŸ¦€: 06 - Ownership: Intro
Fady GA 😎
Fady GA 😎

Posted on • Updated on

Learning Rust πŸ¦€: 06 - Ownership: Intro

This is the first article in the series to discuss a Rust unique trait, Ownership. I'll split the topic into 2 parts to keep it light. So, let's start! 🀩

⚠️ Remember!

You can find all the code snippets for this series in its accompanying repo

If you don't want to install Rust locally, you can play with all the code of this series in the official Rust Playground that can be found on its official page. But for this one, you need a cargo installation on your machine (or a VM).

⚠️⚠️ The articles in this series are loosely following the contents of "The Rust Programming Language, 2nd Edition" by Steve Klabnik and Carol Nichols in a way that reflects my understanding from a Python developer's perspective.

⭐ I try to publish a new article every week (maybe more if the Rust gods πŸ™Œ are generous 😁) so stay tuned πŸ˜‰. I'll be posting "new articles updates" on my LinkedIn and Twitter.

Table of Contents:

Memory management:

As briefly introduced in the first article in the series, a computer programing language has to manage the memory somehow for any computer program that is written in that language, a process called "memory management".

Outside of the "Rust" world, this process is generally done either manually (the programmer's responsibility) or using some sort of garbage collection algorithm(s) (the programming language's responsibility). For Python, it uses garbage collection. Essentially, it's an algorithm to "automatically" identify unused memory blocks by the program then "de-allocate" (free) them. In this great article, you can read all about the details about garbage collection in Python and I guess it will be similar in other languages too πŸ€·β€β™‚οΈ.

Manual memory management, on the other hand, is totally the programmer's responsibility. The programmer has to allocate (assign) memory to the program then de-allocate (free) this memory when the program is done with it. This gives great power to the programmer and if done right, will make the program a lot more efficient and runs without any garbage collection overhead. But this introduces new set of problems:

  • If the programmer forgot to free memory: It will result in something called memory leak where the program is using too much memory overtime.
  • If the programmer frees the memory too soon: This could cause the program to crash or data corruption which both are bad πŸ˜”.

The Stack and the Heap:

One more thing before we discuss Rust's Ownership system and if you know what The Stack and The Heap are, you can skip this section. But for me this was a new thing! πŸ€“

From a programming language's point of view, the computer memory is divided into two "sub-systems" (if we can call them that). One is an organized, known size and, queue-like system which is called The Stack. Entries in the stack must be of known size and are accessed on last-in-first-out basis. You can push (add) items to the stack and pop (delete) items from the stack too but you can't remove an item from the middle of it without popping the preceding items first. Pushing to and Popping from stack is faster than the heap.

The Heap is the less organized cousin of the Stack. Items can be of unknown sizes and can be allocated and de-allocated in any order. Pushing to The Heap is slower than the Stack. When you allocate data to the Heap, you get a pointer to this data because it's of unknown size.

The main point here is that, accessing data in the Stack is faster than the Heap and the data in the Stack must be of a known size at compile time in contrast to the Heap.

Rust Ownership:

Rust has its own unique way to do memory management. It uses Ownership which is the following 3 simple rules:

  1. The value in Rust must have an owner.
  2. Every value must have only one owner at a given time.
  3. When the owner goes out-of-scope, the value is dropped.

Following those rules, Rust has managed to enforce memory safety by avoiding the problems of manual memory handling and avoided the use of garbage collection which usually improves performance. You may wonder, "What exactly are those? scope and owner??!!". Don't worry, I'll talk about that, next πŸ˜‰.

Scopes in Rust:

Scope in Rust is the range where this value (variable) is valid. A variable is valid starting from its declaration till its current scope ends.

fn main() {
    // Start of "main" function scope.
    let x = 5;
    println!("Value of x from 'main' scope is {x}");

    {
        // Start of "internal" scope.
        let y = 10;
        println!("Value of y from internal scope is {y}");
        println!("Value of x from 'internal' scope again is {x}");
    } // End of "internal" scope.

    println!("Value of y from 'main' scope is {y}"); // Error: cannot find value `y` in this scope
    println!("Value of x from 'main' scope again is {x}");
} // End of "main" function scope
Enter fullscreen mode Exit fullscreen mode

Go ahead and run this code. The program will panic due to this line println!("Value of y from 'main' scope is {y}"); giving the following error:

cannot find value `y` in this scope
Enter fullscreen mode Exit fullscreen mode

Which is pretty much the same as in Python and any other language. But this isn't all about scopes. As always with Rust, there are some differentiating caveats regarding scopes which we will explore in part 2.

In this short article, we discussed some theory about Rust Ownership. In part 2, we will go deeper and build upon the topic of this article and start exploring the String type as an example to demonstrate the Ownership concepts. See you then πŸ‘‹.

Top comments (0)