# Debugging Rust in QtCreator

**Want to get straight to the juice? Here's the repository with the helpers.py file for debugging Rust with QtCreator.**

They say debugging is twice as hard as coding in the first place, so if you write the most clever code you can, you can't debug it by definition. Instead, you should write code at most half as clever as you are, so that you are able to actually debug it.

In reality, a lot of your skill depends on your tools, so if you have a bad/good debugger, you have to be more/less careful.

I'm only a human, and I make mistakes: sometimes I write clever code. It's embarrassing to say, but sometimes I even enjoy it. When the inevitable bug appears, I desperately search for any ways to make the chore of debugging easier. For me, that means avoiding a naked *gdb* for something more *visual*. I like to see an overview of variables all at the same time, know their types without asking explicitly, and to be able to see which variables have changed.

Because of those preferences, I use QtCreator as my debugger.

## C? C++? Rust?

QtCreator has been built with C and C++ in mind. That's all fine, but when I use Rust, it doesn't really know what to do with the variables I want to see. It doesn't understand enums, inserting weirdly named fields into them, and it gets completely lost when it comes to showing the contents of a slice or a string. Take a look at what a String looks like:

QtCreator displays String as a deply nested structure

And now at this `Option::None` value:

QtCreator displays None in a nested way, including an inaccessible None variant and a #1 field with "0" in it

That's not great. Slices, strings, and enums like Option or Result are Rust's bread-and-butter. It's challenging to write any code without those. Does that mean that I have to go back to gdb? Gdb understands Rust, after all:

```
test::printn (n=...) at test.rs:57
57          println!("{:?}", n);
(gdb) p n
$2 = test::Newtype (5)
```

...more or less:

```
test::printS (t=...) at test.rs:33
33          println!("{}", t);
(gdb) p t
$1 = alloc::string::String {vec: alloc::vec::Vec<u8, alloc::alloc::Global> {buf: alloc::raw_vec::RawVec<u8, alloc::alloc::Global> {ptr: core::ptr::unique::Unique<u8> {pointer: core::ptr::non_null::NonNull<u8> {pointer: 0x5555555abaa0}, _marker: core::marker::PhantomData<u8>}, cap: 3, alloc: alloc::alloc::Global}, len: 3}}
(gdb) c
test::printSl (s=...) at test.rs:73
73          println!("{:?}", s);
(gdb) p s
$5 = &[u8] {data_ptr: 0x555555598061, length: 2}
```

## Helpers

Worry not. QtCreator's authors were smart enough to predict the need for such functionality. They provided a hook for something called "debugging helpers". Those are small programs which interact with QtCreator's gdb's session in order to turn the data into something the debugger panel can understand.

Long story short, I spent a bunch of time hacking a helpers.py file which you can put into QtCreator, and which decodes the most common Rust types. Get it in my Framagit repository and read the README.

QtCreator presents human-readable contents of a Vec<String> in a readable way

## Limitations

The project for which I needed this didn't make use of many types, so many things from the standard library are missing and may not work. Things like Path[Buf], OsStr[ing], Cells, Mutex, Arc are completely untouched. They shouldn't be hard to add, though. Patches accepted!

Beware! Rust doesn't have a stable ABI for the debug information, so those helpers are tuned for binaries produced with a specific version of Rust. I'll try to keep them up to date, but it's not a guarantee.

Finally, because I try to keep compatibility with plain C and with C++, I keep building on the basic helpers provided by QtCreator. Honestly, they are not thought out that great, and they need a rewrite, but instead I monkey-patch what was needed. If your answer it "well, contribute it upstream", then I'll just make it clear that I refuse to sign over my rights to the code by signing the Qt Company's Contributor License Agreement. Qt Company: if you're reading this, you're allowed to take the code under the terms of the GPLv3, but you do not get the permission to relicense it, just like I didn't.

Written on .

Comments

dcz's projects

Thoughts on software and society.

Atom feed