Skip to content
Tech News
← Back to articles

Visualizing Rust's Vtables: How dyn Trait Works In Memory

read original get Rust Atomics and Locks by Mara Bos → more articles
Why This Matters

A hands-on explainer that dissects how Rust's dyn Trait dynamic dispatch is laid out in memory, contrasting it with C++ virtual functions and CRTP. For developers moving between systems languages, it clarifies a common point of confusion: Rust uses fat pointers with separate vtables rather than embedding a vtable pointer in the object. It also cautions against learning Rust purely by mapping it onto C++ idioms.

Key Takeaways
Worth a Look

Rust Atomics and Locks by Mara Bos — The article's author credits Mara Bos' book as a core learning resource, and this is it — a deep dive into Rust concurrency, memory ordering and low-level internals. If you enjoy dissecting what Rust actually does in memory, it's a natural next read after poking at vtables.

See Rust Atomics and Locks by Mara Bos on Amazon → Affiliate link — we may earn a commission on purchases, at no extra cost to you. Product picked by AI based on this article; it is not a tested recommendation.

I’m venturing into Rust and it’s both satisfying and mind-boggling at the same time. So far I’ve been learning from the book and Mara Bos’ book, but I got the itch to do some dissecting myself. My initial goal of these experiments was to compare Rust’s approach to polymorphism with C++’s. Ultimately, however, as I’ve come to realize, it’s a bit of a trap when trying to understand a new language through another one to try to draw 1:1 parallels. It might seem like it helps, but at the end of the day, we can’t treat Rust as C++ with different syntax. If that were the case, there’d be nothing revolutionary about it.

That said, I believe there is merit in poking around and coming to understand the why. So, if you’re like me and need to know what exactly is happening in memory, in order to feel like you truly understand the concepts, hopefully you’ll find this post useful :)

By the way, the thumbnail image is a photo of the rust fungus, to which we owe Rust’s name. Credit: gailhampshire from Cradley, Malvern, U.K, CC BY 2.0, via Wikimedia Commons.

You can find all the code and experiments on GitHub.

Introduction: The Crux of the Matter

What we’re trying to achieve is quite simple. Let’s say we have a bunch of shapes: circles, squares, triangles, and we want to call draw() on each one.

C++ Approach #1: Virtual Functions

The first way to do this that comes to mind in C++ is through virtual functions, which makes use of runtime polymorphism. The vtable pointer lives inside the object, virtual dispatch happens automatically.

std :: vector < Shape *> shapes = { new Circle (), new Square () }; for ( auto * s : shapes ) s -> draw ();

Rust’s equivalent would be dyn Trait , which is what we ultimately want to understand. But first, let’s take a look at another way we could solve this in C++.

... continue reading