CS110L L3 - Memory Safety in Rust

Last

Warning

If someone is reading this blog, please be aware that the writer did not consider the experience of the other readers.
After all, the most important part is about writing things down for better memorization.

Memory Management

Ownership in C

  • There’s actually no ownership design in C, which means that the language, or more specifically the compiler, does not check anything about ownership, leaving the burden to the programmers.

  • For example, look at the declaration of the function below:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    /**
    * dvb_unregister_frontend() - Unregisters a DVB frontend
    *
    * @fe: pointer to &struct dvb_frontend
    *
    * Stops the frontend kthread, calls dvb_unregister_device() and fress the
    * private frontend data allocated by dvb_unregister_frontend().
    *
    * NOTE: This function doesn't free the memory allocated by the demod,
    * by the SEC driver and by the tuner. In order to free it, an explicit call to
    * dvb_frontend_detach() is needed, after calling this function.
    */
    int dvb_unregister_frontend(struct dvb_frontend *fe);
  • Just from the doc comment for this function, you can tell that the memory management process is like messy. Programmers should be cautious when invoking those functions, carefully reading doc comment for each one to understand the ownership implications.

  • Not only that, the memory area pointed to by the pointer taken as a parameter in this function cannot be freed with free(), there’s a specific function called dvb_frontend_detach responsible for destroying that heap-allocated memory.

  • Even worse, the data structure pointed by the pointer might need multiple different functions to free the memory allocated earlier. This can be very complicated and prone to mistakes, leading to memory corruption or memory leak.


  • As a result, it is really difficult to handle the creation and destruction of heap areas in C manually. It is very common to forget about clearing up memory areas after using them, or dereference pointers pointing to memory areas that have been freed already early on, which would cause a seg fault.

Ownership in Rust

  • Rust addresses this problem with a unique concept: ownership.

    Ownership is Rust’s most unique feature and has deep implications for the rest of the language. It enables Rust to make memory safety guarantees without needing a garbage collector, so it’s important to understand how ownership works.

  • Three ownership rules:

    1. Each value in Rust has an owner.
    2. There can only be one owner at a time.
    3. When the owner goes out of scope, the value will be dropped.

Ownership with Rust Exmaples

1
2
3
4
5
6
7
8
9
fn log(s: String) {
println!("{}", s);
}

fn main() {
let s = String::from("hello");
log(s);
log(s);
}
  • The code above won’t compile. Reason is that the first time we invoke log on s, the function takes the ownership of the string so the second time we call it, s no longer owns the string "hello" anymore.

  • In other words, the memory that stores the string "hello" would have been freed after the first call to log(s).

  • Here we can see that Rust is trying to make sure that every value is not NULL or None when they are used, in a very strict way. Any manipulation(i.e., borrowing) of the value is treated with caution; hence, the value is often not allowed after such an operation.

  • In C, where the allocation and deallocation of the memory is controlled manually by the programmer, you can free the buffer s anywhere in the code. Either after the first time calling log, or the second time, or even inside the log function(right after printing the string to the standard output). This seems manageable in a simple example like the one above, but you can’t make that promise anymore when the complexity of the code grows. (Reality has proven this.)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void log(char *s) {
    printf("%s\n", s);
    // free(s); ?
    }

    int main() {
    char *s = strdup("hello");
    log(s);
    // free(s); ?
    log(s);
    // free(s); ?

    return 0;
    }
    • You might encounter use-after-free or double-free issue, or even memory leak if you forget to free the buffer.

1
2
3
4
5
6
7
8
fn main() {
let s = String::from("hello");

let s1 = &s;
let s2 = &s;

println!("{} {} {}", s, s1, s2);
}
  • This code compiles without error. & stands for borrowing (i.e., referencing), which does not tranfer the ownership from its original owner.

  • However if we change one of the references to a mutable reference, like the way down below:

    1
    2
    let s1 = &mut s;
    let s2 = &s;
  • Then it won’t compile. This introduces another rule about borrowing:

    • At any given time, you can have either one mutable reference or any number of immutable references.
  • The purpose of this rule is easy to understand: You don’t want the data you’re reading to change unexpectedly. So Rust enforces that only one entity may mutate a value at a time, and during mutation, no other entity may read or write to it. But it’s okay that more than one guy reading from the same value, as long as none of them is modifying it.

Error Handling

TODO

To Be Continued…

  • Title: CS110L L3 - Memory Safety in Rust
  • Author: Last
  • Created at : 2025-05-01 17:04:00
  • Link: https://blog.imlast.top/2025/05/01/cs110l-l3/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments
Nickname
Email
Website
0/500
  • OωO
  • |´・ω・)ノ
  • ヾ(≧∇≦*)ゝ
  • (☆ω☆)
  • (╯‵□′)╯︵┴─┴
  •  ̄﹃ ̄
  • (/ω\)
  • ∠( ᐛ 」∠)_
  • (๑•̀ㅁ•́ฅ)
  • →_→
  • ୧(๑•̀⌄•́๑)૭
  • ٩(ˊᗜˋ*)و
  • (ノ°ο°)ノ
  • (´இ皿இ`)
  • ⌇●﹏●⌇
  • (ฅ´ω`ฅ)
  • (╯°A°)╯︵○○○
  • φ( ̄∇ ̄o)
  • ヾ(´・ ・`。)ノ"
  • ( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
  • (ó﹏ò。)
  • Σ(っ °Д °;)っ
  • ( ,,´・ω・)ノ"(´っω・`。)
  • ╮(╯▽╰)╭
  • o(*////▽////*)q
  • >﹏<
  • ( ๑´•ω•) "(ㆆᴗㆆ)
  • 😂
  • 😀
  • 😅
  • 😊
  • 🙂
  • 🙃
  • 😌
  • 😍
  • 😘
  • 😜
  • 😝
  • 😏
  • 😒
  • 🙄
  • 😳
  • 😡
  • 😔
  • 😫
  • 😱
  • 😭
  • 💩
  • 👻
  • 🙌
  • 🖕
  • 👍
  • 👫
  • 👬
  • 👭
  • 🌚
  • 🌝
  • 🙈
  • 💊
  • 😶
  • 🙏
  • 🍦
  • 🍉
  • 😣
  • 颜文字
  • Emoji
  • Bilibili
0 comments
No comment