Carbon memory safety: a first deep dive

coffeeaddict11 pts1 comments

Carbon memory safety: a first deep dive (v3)

Carbon memory safety

A first deep dive

https://chandlerc.blog/slides/2026-memory-safety-deep-3/

Hello, I’m Josh Levenberg from the Carbon programming language team.

This is an early preview of Carbon’s memory safety model, that we have been hard at work on and is now ready for community feedback.

Presentation is going to focus mainly on the question “what is Carbon’s memory safety design”, with a little bit of comparison to Rust.

You can see a copy of these slides at that URL, with speaker notes available.

click

This is just the first chapter, not the full Carbon memory safety story:

There is more to the design than I will cover

I won’t be covering how we arrived at this design, other models we considered, and why we prefer this approach.

There won’t be much about implementing this design, we are coming to you early so we can incorporate your feedback while things are still flexible

I also would like to make clear that this is the result of a collaboration with multiple members of the Carbon team and community, not just me.

Goal of Carbon’s memory safety design

Smooth and incremental transition from C++ to memory safety in Carbon

Result needs to be memory safe

Expressivity to represent common C++ code patterns

Makes the transition smooth

Incremental in two ways

Migrate to Carbon a little at a time

Incrementally add safety once migrated

Clear goals lead to good designs.

These goals are different than other languages, like Rust.

The differences in the design of Carbon’s memory safety arise from the differences in goals.

There are three components of this goal

click Compiler-checked memory safety, either at compile-time or runtime

Two modes: permissive and strict

Permissive mode, along with C++ interop, supports incremental migration

Allows code that doesn’t yet have safety annotations

Strict Carbon is fully memory safe

The destination; goal is to migrate all code to strict mode

Strict Carbon is fully memory safe

Temporal: Preventing “use after free” (UAF) at compile time

Spatial: Runtime bounds checking as in ๐Ÿฆ€ Rust and being added to C++

Type, initialization, null pointer, and data race safety

In this talk I’m only going to talk about the compile-time safety enforcement, with a focus on preventing use after free.

I will briefly touch on initialization safety and data race safety.

Expressivity

Non-exclusive mutable pointers

Directly proving existing correct C++ code is memory safe

Support for C++ features like inheritance and specialization

More expressive than Rust, but with a complexity and verbosity cost

Allows smooth migration of C++

Code patterns translate without cliffs, rearchitecting, or lots of unsafe

I want to be clear that when I compare Carbon to Rust and say it has greater expressivity, I’m not saying Rust has made a mistake in its safety model, or that we expect Carbon to be a replacement for Rust. Rust has a proven safety model that has been shown to work well across many classes of programs. Carbon aims to be complementary, targeting the specific use case of C++ migration, where gaining expressivity at a cost of more complexity and verbosity is a more worthwhile trade-off.

Temporal safety

Preventing use after free at compile time

Anatomy of a use after free (C++)

#include<br>#include

int main() {<br>`std::vector x { 1, 20, 300 }`;<br>`int* p = &x[0]`;<br>`x.push_back(4000)`;<br>printf("%d\n", `*p`); //

Allocation

Capture a pointer into allocation

Free or reallocation

Use of dangling pointer

This is a minimal example of use after free.<br>Every use after free has four steps. Click

To have a &ldquo;free,&rdquo; you need an allocation. Here, the C++ standard vector type allocates on the heap to store its elements.

To have a &ldquo;use,&rdquo; you need to capture an address into the allocation.

The &ldquo;free&rdquo; is any deallocation or reallocation that invalidates the captured address.

And finally we have the &ldquo;use&rdquo; after the free, dereferencing the dangling pointer p.

Anatomy of a use after free (Carbon)

import Core library "io";

fn Run() {<br>// ``buf(T)`` is Carbon's equivalent of C++'s<br>// ``std::vector`` or Rust's ``Vec``<br>`var x: buf(i32) = (1, 20, 300)`;<br>`var p: i32* = &x[0]`;<br>`x.PushBack(4000)`;<br>// โŒ Compiler error: use of ``p`` after it was<br>// invalidated by ``x.PushBack(4000)``.<br>Core.Print(`*p`);

Allocation

Capture a pointer into allocation

Free or reallocation

Prevents use of dangling pointer

In Carbon, the code looks similar, except for it uses Carbon&rsquo;s buf type, which is its equivalent for C++&rsquo;s vector or Rust&rsquo;s vec.

The steps are the same, but the compiler gives an error.

No safety annotations in the calling code

import Core library "io";

fn Run() {<br>// ``buf(T)`` is Carbon's equivalent of C++'s<br>// ``std::vector`` or Rust's ``Vec``<br>var x: `buf`(i32) = (1, 20, 300);<br>`var p:...

carbon safety memory rsquo free rust

Related Articles