1 Month of Learning Rust - Ownership

1 Month of Learning Rust - Ownership

Daily short news for you
  • For over a week now, I haven't posted anything, not because I have nothing to write about, but because I'm looking for ways to distribute more valuable content in this rapidly exploding AI era.

    As I shared earlier this year, the number of visitors to my blog is gradually declining. When I looked at the statistics, the number of users in the first six months of 2025 has dropped by 30% compared to the same period last year, and by 15% compared to the last six months of 2024. This indicates a reality that users are gradually leaving. What is the reason for this?

    I think the biggest reason is that user habits have changed. They primarily discover the blog through search engines, with Google being the largest. Almost half of the users return to the blog without going through the search step. This is a positive signal, but it's still not enough to increase the number of new users. Not to mention that now, Google has launched the AI Search Labs feature, which means AI displays summarized content when users search, further reducing the likelihood of users accessing the website. Interestingly, when Search Labs was introduced, English articles have taken over the rankings for the most accessed content.

    My articles are usually very long, sometimes reaching up to 2000 words. Writing such an article takes a lot of time. It's normal for many articles to go unread. I know and accept this because not everyone encounters the issues being discussed. For me, writing is a way to cultivate patience and thoughtfulness. Being able to help someone through my writing is a wonderful thing.

    Therefore, I am thinking of focusing on shorter and medium-length content to be able to write more. Long content will only be used when I want to write in detail or delve deeply into a particular topic. So, I am looking for ways to redesign the blog. Everyone, please stay tuned! 😄

    » Read more
  • CloudFlare has introduced the pay per crawl feature to charge for each time AI "crawls" data from your website. What does that mean 🤔?

    The purpose of SEO is to help search engines see the website. When users search for relevant content, your website appears in the search results. This is almost a win-win situation where Google helps more people discover your site, and in return, Google gets more users.

    Now, the game with AI Agents is different. AI Agents have to actively seek out information sources and conveniently "crawl" your data, then mix it up or do something with it that we can't even know. So this is almost a game that benefits only one side 🤔!?

    CloudFlare's move is to make AI Agents pay for each time they retrieve data from your website. If they don’t pay, then I won’t let them read my data. Something like that. Let’s wait a bit longer and see 🤓.

    » Read more
  • Continuing to update on the lawsuit between the Deno group and Oracle over the name JavaScript: It seems that Deno is at a disadvantage as the court has dismissed the Deno group's complaint. However, in August, they (Oracle) must be held accountable for each reason, acknowledging or denying the allegations presented by the Deno group in the lawsuit.

    JavaScript™ Trademark Update

    » Read more

The Issue

In JavaScript and some other languages, you often hear phrases like "memory leak." This happens when an application consumes more memory than it needs. There are various reasons for this issue, one of which is improper memory deallocation.

The challenge in languages with automatic garbage collection is how to release memory correctly and in the right place and time. The fundamental idea behind them is, "just keep running, and I'll take care of cleaning up the mess." But how do you know if a variable is still needed or not? That's the job of a garbage collector algorithm. Although we often hear about exciting garbage collector algorithms, sooner or later, memory exhaustion remains a problem.

Automatic Garbage Collection

I believe many of you are familiar with the syntax malloc and free in the C programming language. malloc allocates memory for a variable, and free deallocates it. The reason for this is that C does not have built-in automatic garbage collection, so we have to declare and free memory manually. This allows programmers to control the amount of memory that a program is allowed to use. However, what happens if they forget to free a variable they malloced, or if they free it twice? Manual memory allocation leads to human errors.

In Rust, we don't have automatic garbage collection, and there's no mechanism for manual memory allocation/deallocation. So, how does Rust manage memory?

Ownership

Let's start with a simple example.

fn main() {
    let a: i32 = 1;
    let b: i32 = a;
    println!("a = {}", a);
    println!("b = {}", b);
}

Running this program, we see two lines printed: "a = 1" and "b = 1". There's nothing strange about it; b = a clearly means that b is also equal to 1.

Now, let's move on to the next example.

fn main() {
    let a = String::from("a");
    let b = a;
    println!("a = {}", a);
    println!("b = {}", b);
}

Of course, the result is "a = a" and "b = a," right? But in reality, this program results in an error.

Due to Rust's ownership system, the value a initially holds a String with the value "a." After declaring b = a, we have effectively transferred ownership of the String "a" from a to b. As a result, a no longer holds any value, and it gets deallocated.

Hold on a second; in the first example, didn't a get assigned to b as well? It's quite simple in that case. i32 is a value stored on the stack, and when you assign one stack variable to another in Rust, it directly takes the value to assign. It's like declaring b = 1.

In contrast, a String is a value stored on the heap. Rust explains that copying values from the heap is costly and unsafe. Therefore, in combination with ownership, the value on the heap is transferred to the assigned variable. You have effectively transferred ownership. Rust does not allow the same behavior as in JavaScript, where assigning one variable to another creates a reference. In Rust, ownership is moved when necessary.

In Rust, there are several ways to create data stored on the heap, such as Vec, String, HashMap, or Box. Therefore, you should be cautious when working with any data stored on the heap to avoid losing ownership.

So, ownership in Rust is a principle of managing the heap, including:

  • All data on the heap must be owned by exactly one variable.
  • Rust frees heap data when its owner goes out of scope.
  • Ownership can be transferred by assignment or by passing it as a function parameter.
  • Heap data can only be accessed through its current owner.

Back to the example, is there a way to assign a value without transferring ownership? Simply use the "clone" method to make a copy.

let a = Box::new([0; 1_000_000]);
let b = a.clone();

clone copies the data to a different memory location and assigns it to b. Therefore, the assignment no longer transfers ownership, and a is not deallocated temporarily.

Ownership transfer not only occurs in value reassignment but also in function parameters. For example:

fn main() {
    let first = String::from("Ferris");
    let full = add_suffix(first);
    println!("{full}, originally {first}"); // first is now used here
}

fn add_suffix(mut name: String) -> String {
    name.push_str(" Jr.");
    name
}

add_suffix is a function that takes name of type String as a parameter. At first glance, you might expect the result to be "Ferris Jr., originally Ferris." However, in reality, the program produces an error.

In fact, when you call add_suffix(first), ownership of first is transferred to add_suffix, and then it is deallocated. Therefore, the println! statement to print the value of first results in an error.

You might wonder why the parameter of add_suffix is written as mut name: String. Recall that all variables are immutable by default in Rust. Only when declared with mut can they be assigned a new value. So, within the function, name.push_str(" Jr.") is allowed because push_str mutates the data.

To solve this issue, we can do the following:

fn main() {
    let first = String::from("Ferris");
    let (first, full) = add_suffix(first);
    println!("{full}, originally {first}"); // first is now used here
}

fn add_suffix(name: String) -> (String, String) {
    let mut suffix_name = name.clone();
    suffix_name.push_str(" Jr.");
    (name, suffix_name)
}

Instead of returning only name, add_suffix now returns both name and suffix_name. The idea here is to return both the original name and the new name so that we can reassign them using let (first, full) = add_suffix(first). In the end, we still have first and full in existence. However, this approach is not the best. Instead, Rust introduces the concept of References and Borrowing.

We can reference variables with data on the heap and "borrow" them using &.

fn main() {
    let m1 = String::from("Hello");
    let m2 = String::from("world");
    greet(&m1, &m2);
    let s = format!("{} {}", m1, m2);
}

fn greet(g1: &String, g2: &String) {
    println!("{} {}!", g1, g2);
}

Although m1 and m2 are used as parameters for greet, they are just "borrowed" values. The variables declared as &m1 and &m2 are borrow variables; they point to borrowed variables without actually owning the values.

Borrowing Data in Rust

There might be some confusion here, but don't worry. I've had to read and reread the ownership concept many times, and I still don't fully grasp it. Therefore, I recommend checking out the Understanding Ownership section in the Rust documentation for a more detailed explanation.

Finally, the good news is that Rust has a powerful code checker. Remember, before running a program, we need to compile it into machine code. During the compilation process, Rust checks everything, such as syntax and ownership-related errors. So, Rust will immediately remind you if you've done something wrong.

Summary

In this article, I've introduced the concept of ownership in Rust, which is a principle for managing heap memory since Rust lacks automatic garbage collection. However, there's more to it, and we'll delve deeper into the principles of ownership in the next article!

Premium
Hello

Me & the desire to "play with words"

Have you tried writing? And then failed or not satisfied? At 2coffee.dev we have had a hard time with writing. Don't be discouraged, because now we have a way to help you. Click to become a member now!

Have you tried writing? And then failed or not satisfied? At 2coffee.dev we have had a hard time with writing. Don't be discouraged, because now we have a way to help you. Click to become a member now!

View all

Subscribe to receive new article notifications

or
* The summary newsletter is sent every 1-2 weeks, cancel anytime.

Comments (0)

Leave a comment...