If you work in safety-critical embedded software, whether it’s automotive, aerospace, or medical devices, you have likely noticed the growing conversation around Rust. Regulatory bodies, defense agencies, and tech giants are investing millions into the ecosystem.
But from a pragmatic perspective, Rust is not a silver bullet. It has yet to achieve the ecosystem maturity required to serve as a seamless, drop-in replacement for C or C++ in rigorously qualified, safety-critical systems.
As someone who loves C and C++ and has spent over 15 years developing autonomous systems with them, I know how powerful these languages are. I also know that toolchains, qualification frameworks, and guidelines for Rust are still actively being written. There is an immense amount of work left to do.
However, we cannot ignore why this massive investment is happening. It is driven by a stark reality: we build systems where software failure doesn’t just mean an application crash, it can cause physical harm, lose lives, and destroy a company’s reputation overnight.
We need to approach safety with the engineering rigor it deserves.
Why Finding Memory Bugs Early Matters
In C and C++, memory management relies heavily on human discipline and strict adherence to coding standards (like MISRA C). If a developer miscalculates a pointer by a single byte, or reads a variable a millisecond after its memory is deallocated, the system enters the territory of Undefined Behavior (UB).
At best, UB causes a segmentation fault. At worst, it creates silent data corruption or severe security flaws like Out-of-Bounds Writes (CWE-787) or Use-After-Free errors (CWE-416).
The critical issue in embedded development isn’t just that these bugs happen, it’s when they are caught.
When a memory bug escapes localized unit testing and makes it into hardware integration or production, the cost to isolate, fix, and recertify the system doesn’t just double, it scales exponentially, often by a factor of 30x to 100x.

The Cost of Delayed Bug Fixes (Adapted from NIST)
The Tooling Dilemma: Detection vs. Prevention
For decades, our industry has fought this by layering on external verification tools: Static Analysis (linters that analyze code without running it) and Dynamic Analysis (like AddressSanitizer [ASan], which monitors memory during execution).
These tools are excellent, indispensable, and necessary. But they have fundamental architectural limits.
Static Analysis Limits: These tools rely on heuristics to predict control flow. They struggle to perfectly trace complex, inter-procedural data states. This leads to a difficult trade-off: dealing with thousands of false positives that engineers eventually fatigue of reviewing, or missing subtle edge cases entirely.
Dynamic Analysis Limits: Tools like AddressSanitizer catch bugs at runtime, meaning they can only flag errors that actually trigger during execution. If an invalid memory read accidentally lands on a valid address during a specific test run, the tool will miss the vulnerability entirely.
To see this architectural gap clearly, look at a classic embedded pattern: Storage Overlaying (using a single memory region for different data types to conserve RAM).
The C/C++ Approach: Raw Unions
In C, a union allocates a single block of memory for multiple data types, but the compiler does not track which type is currently active.
union payload {
int integer;
int *pointer;
};
// 1. Store integer payload
union payload data = {
.integer = 2026
};
// 2. Accidentally read as a memory address
// Segmentation Fault
int value = *data.pointer;
To mitigate this, we use "Tagged Unions" (pairing the union with an enum tag). However, the C and C++ compiler never forces you to check the tag before accessing the memory. If an engineer forgets the conditional check, the code still compiles perfectly, leaving a latent memory safety violation in the system.
The Rust Approach: Type-Safe Enums
Rust addresses this specific problem by embedding the concept of a tagged union directly into the language syntax via algebraic data types (enums).
enum Payload {
Integer(i32),
Pointer(Box<i32>),
}
// 1. Store integer payload
let data = Payload::Integer(2026);
// 2. The compiler forces explicit verification
// Only the matching branch executes
// Type confusion is impossible
let value = match data {
Payload::Integer(i) => i,
Payload::Pointer(p) => *p,
};
You cannot accidentally bypass this check. The cognitive load of protecting that memory boundary is shifted from the engineer’s memory to the compiler architecture.
A Pragmatic Path Forward
Rust is not fully mature for every safety-critical domain yet, but its core value proposition is clear: it moves an entire class of memory-safety and data-race anomalies from runtime detection to compile-time prevention.
Moving forward, the strategy isn’t about throwing away C and C++ overnight. It is about understanding how to safely bridge the two worlds. By leveraging Rust’s strict compile-time guarantees (Ownership and Borrowing) alongside verified C and C++ codebases, we can design systems that are fundamentally more robust.
We must stop relying solely on improving the external tooling to catch human errors. It is time to consider language design as an active component of our safety engineering strategy.
Behind the Scenes: Safety-Critical Rust
I’m currently developing a specialized curriculum for engineers looking to move beyond surface-level tutorials toward building verifiable, deterministic systems.
The upcoming Safety-Critical Rust course focuses deeply on the practical realities of our industry:
Mastering Rust Interoperability: Hardening the integration boundaries between Rust and C and C++ codebases.
Verification Frameworks: Maximizing the utility of compiler diagnostics, static analysis, and rigorous testing architectures.
Risk Management: Developing a clear mental model for tracing risk directly from system requirements down to production code.
Ready to see what I’m building? Learn more about the course.
If you want to track the course development, read early chapter drafts, and get technical notes on compliance frameworks like ISO 26262, DO-178C, and IEC 62304, join the waitlist today. Early adopters receive exclusive access and a 50% discount when the course officially launches.
👉 Secure your spot: Join the Safety-Critical Rust Waitlist

The Safety Stack newsletter
