Skip to main content

Blog

Article Search

Rust Revolutionizes Embedded

By: Kaitlin Berryman

Programming languages that implement manual memory management (C, C++) give the programmer complete control over what’s happening in memory... but at what cost? Even one small mistake can lead to undefined behavior and security risks.

“Around 70 percent of all the vulnerabilities in Microsoft products addressed through a security update each year are memory safety issues; a Microsoft engineer revealed last week at a security conference.” https://www.zdnet.com/article/microsoft-70-percent-of-all-security-bugs-are-memory-safety-issues/

Programming languages with a garbage collector (Python, Java, Go, etc.) successfully prevent many memory management errors, but at the expense of performance. These languages are known for being less performant than languages with manual memory management. Garbage collection happens at runtime, meaning that not only your program is running, but so is the garbage collector. This creates a “Stop the World” problem, where garbage collectors halt your program’s execution entirely to go through and manage memory. Because of this, languages utilizing garbage collectors sacrifice performance for memory safety.

Wouldn’t it be nice to have a language that enforces memory safety and performs as well as C does?

Meet Rust.

“Rust is an open-source systems programming language that focuses on speed, memory safety and parallelism.” https://research.mozilla.org/rust/

“High-level ergonomics and low-level control are often at odds in programming language design; Rust challenges that conflict.” https://doc.rust-lang.org/book/

Before diving deeper, I want to specify that this entire blog assumes we’re working with “safe Rust” versus “unsafe Rust” which is used when you want the compiler to look the other way and trust you as a programmer.

Ownership

Rust’s ownership model is a set of rules that the compiler checks at compile-time. If there’s code that doesn’t meet these standards, the compiler will give you a detailed error message. While the code might take longer to compile with all these rules, it doesn’t affect runtime execution and the programmer is confident that the code is safe from many memory bugs.

If you want to know more about Rust's ownership model, check out the official Rust Book. https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html

No Null

Null, a built-in constant used to indicate that the expected value is unknown, is a fundamental concept in many programming languages. But null breaks many assumptions you can make about programming languages, which is one reason null pointers generate so many bugs.

“Speaking at a software conference in 2009, Tony Hoare apologized for inventing the null reference: I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.” https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions

Instead of null, Rust has the Option type. The Option type contains Some or None, which forces you to consider what would happen in the absence of data. Null can’t sneak up on you anymore.

Memory Problems & Undefined Behavior

Programming in C requires constantly being on the lookout for memory bugs. That's not the case when you are programming in Rust. When your Rust program compiles you can be confident it is free of memory bugs.  The following are a few examples of the types of memory issues Rust manages really well:

Uninitialized Memory
Let’s take a second to talk about stack memory. “The Stack” is a chunk of memory reserved for saving the data we need in a program. Let’s say that we run our program and begin our first function. Each time a function is executed, memory for its data is pushed onto the stack.

Declaring a variable reserves an open spot in stack memory, and initializing a variable writes a value at that memory address. When the function returns, we don’t need its local variables anymore, so the memory of that stack frame can be overwritten.

If we declare a variable on the stack but we don't initialize a value or write data to the stack, then what's there? Is it zero?  Is it random data? Are we even allowed to access what’s there? Different programming languages handle this problem differently. If accessing this uninitialized memory is allowed, it could be anything. It could be the data from the previous function, previous programs, or just random data. This undefined behavior causes general security concerns.

C allows us to access uninitialized memory. Rust prevents us accessing uninitialized memory. The compiler will simply throw an error and tell us where to fix the bug.

Null Pointer Dereference
A pointer references and stores a memory address. Dereferencing a pointer refers to retrieving the data stored at the pointer’s location in memory. A null pointer dereference happens when a program tries to dereference a pointer, but instead of the pointer being a valid reference, it’s actually null. This is undefined behavior, which may crash the program. Attackers may intentionally dereference a pointer to try to get around program security.

C, C++, and Java allow null pointer dereferences to occur. Rust prevents null pointer dereferences, because null simply doesn’t exist in Rust.

Use-After-Free / Dangling Pointers
Use-After-Free (UAF) is a common vulnerability in languages with manual memory management. When memory on the heap is freed, the pointer to that memory becomes invalid and shouldn’t be used again. If the pointer is used again, a UAF vulnerability is created, which can lead to data corruption, program crashes, and general security risks.

Let’s say that two pointers point to the same bunch of memory on the heap, and one pointer frees the memory. The other is left as a dangling pointer, which leads to undefined behavior if it’s deferenced. Dereferencing a dangling pointer may leak unrelated data, cause segfaults, and create hidden bugs.

C allows dangling pointers to be dereferenced. Rust prevents dangling pointers from existing because of its ownership and lifetime model.

Double Free
A double free vulnerability happens when the program calls free() on a pointer that it shouldn’t have access to.

C and C++ allow programmers to double-free pointers. Rust prevents programmers from double-freeing pointers.

Data Races
Multithreading allows multiple threads to run simultaneously. However, data races in multithreaded code lead to undefined behavior. For example, you have two threads, and they share a variable named x with a value of two. The first thread tries to overwrite x to have value five, and the second program tries to overwrite x to have the value of 10. So… does x equal five or ten? It could be either! Data races happen when at least two threads are accessing the same memory, while at least one of the threads is writing to the memory.

C allows data races. Rust prevents data races.

These are just a few examples of how Rust is great at managing memory bugs

Performance

Different programming languages will be faster and slower at different tasks because they’re optimized differently. However, benchmarks and testing show patterns in the runtime performance of various languages. Benchmarks show that Rust’s runtime performance in many cases is just as fast as C/C++. Check out these benchmarks for yourself

1 — https://benchmarksgame-team.pages.debian.net/benchmarksgame/index.html

Rust vs. C (gcc compiler)

● Rust is faster in 4/10 of the benchmarks

● C is faster in 2/10 of the benchmarks

● They're basically identical in 4/10 of the benchmarks (+/- 0.04 secs)

Rust vs. C (Clang compiler)

● Rust is faster in 6/10 of the benchmarks

● C is faster in 1/10 of the benchmarks

● They're basically identical in 3/10 of the benchmarks (+/- 0.04 secs)

Rust vs. C++ (G++ compiler)

● Rust is faster in 3/10 of the benchmarks

● C++ is faster in 4/10 of the benchmarks

● They're basically identical in 3/10 of the benchmarks (+/- 0.04 secs)

A picture containing diagram

Description automatically generated

 

2 — http://tempesta-tech.com/blog/fast-programming-languages-c-cpp-rust-assembly

Rust vs. C (gcc Compiler)

● Rust is faster in 6/10 of the benchmarks

● C is faster in 2/10 of the benchmarks

● They're basically identical in 2/10 of the benchmarks (+/- 0.04 secs)

Rust vs. C (Clang Compiler)

● Rust is faster in 6/10 of the benchmarks

● C is faster in 1/10 of the benchmarks

● They're basically identical in 3/10 of the benchmarks (+/- 0.04 secs)

Rust vs. C++ (G++ Compiler)

● Rust is faster in 3/10 of the benchmarks

● C++ is faster in 5/10 of the benchmarks

● They're basically identical in 2/10 of the benchmarks (+/- 0.04 secs)

 

3 — https://levelup.gitconnected.com/which-is-faster-rust-or-c-lets-find-out-who-is-the-usain-bolt-87495c774c8 

Timeline

Description automatically generatedChart, bar chart

Description automatically generated

4 — https://julialang.org/benchmarks/

Chart, scatter chart

Description automatically generated

5 — https://pcwalton.github.io/2013/04/18/performance-of-sequential-rust-programs.html

Chart, bar chart

Description automatically generated

6 — https://jaxenter.com/energy-efficient-programming-languages-137264.html#:~:text=Compiled%20languages%20like%20C%2C%20C,%2Defficient%20object%2Doriented%20language

Table

Description automatically generated

7 — https://coresumo.com/scala-3-0-benchmark-scala-3-0-features-scala-3-0-vs-2-13-1-and-2-13-2-and-2-14/

A picture containing text, writing implement, stationary, pencil

Description automatically generated

 

Conclusion

Rust is a great way to create memory-safe, high-performance software. With its safety and speed, is Rust the future of programming? Let's spark some conversation. What do you think?

 

Kaitlin Berryman is a Software Engineering Intern at Geisel Software, Inc. As a student, she's diving into learning Rust, C, C++, Python, iOS development, website development, robotics, CNC machinery, and Electrical Engineering. She's currently attending Rochester Institute of Technology for Electrical Engineering (Robotics Option) and Springboard's Software Engineering Bootcamp. Her goal at Geisel Software Inc is to learn as much as possible as fast as possible.

Other articles in this section

  • How to Keep From Drowning in Technical Debt

    Technical debt is like any other debt, easy enough to get into, but hard enough to get out of.

    Read

  • Embedded Vision: Looking Forward

    Embedded vision technology is growing rapidly and finding its way into applications across the tech spectrum. These embedded systems are comprised of two main elements: a compact camera connected to a compact processing board.

    Read

  • Back to The Office With Big News!

    As companies are returning to the "New Normal", we've reopened our offices following recommended guidelines. We're so excited to be back and we even have some big news!

    Read

  • Author
    Kaitlin Berryman

    Kaitlin Berryman