Does Rust come with its own debugging tool?

Hi,

I'm learning Rust and I would like to know whether Rust core comes with its own debugging tool. I mean is there any official tool which is "recommended" to be used by developers using Rust? For example with Python, there is pdb which comes with Python.

4 Likes

AFAIK the basic Rust distribution doesn't come with a specialized debugger.

However, since Rust compiles down to LLVM, and then machine code, and it supports generating debug info for binaries, you should be able to use any widely-used debugger such as GDB or LLDB.

According to the Rust Compiler Developer Guide, the Rust project has also forked the aforementioned two debuggers in order to add Rust-specific features to them. However, you can still get pretty far with stock GDB or LLDB by pretending that compiled Rust code is C code, except that you won't get pretty symbol names.

Fun fact: don't worry about debuggers too much. During the several (> 4) years I've spent writing Rust, never once did I need to use a debugger. Granted, I haven't written a lot of unsafe code — but that's exactly the point, I guess.

16 Likes

Rust does come with rust-gdb and rust-lldb wrapper scripts that run gdb and lldb with some extra configuration to improve debugging of common Rust types. Other than that, it's the same workflow as debugging C++ or C, so tutorials or documentation that covers that should carry over.

10 Likes

Thanks for the suggestion. So If I understand correctly I have to installed the forked version of the GDB which apparently is more Rust friendly (and not the default version of GDB which comes by my Linux distribution)

https://github.com/rust-dev-tools/gdb

And then I'll to dive into GDB's user guide here

https://sourceware.org/gdb/download/onlinedocs/gdb.pdf

1 Like

Is it just me?

In three decades of using C, C++ and other compiled languages I have never much felt the need to use a debugger like GDB.

Then, on the occasions I have been so stumped as to reach for such a debugger they have turned out to be useless. Especially in threaded or time critical code where stepping though with a debugger tends to hide the problem. Useless for detecting memory leaks. Pretty useless for detecting memory corruptions that don't show up as a problem til thousands or millions of instructions later, in some unrelated part of the code.

Enter Rust. With it's fussiness about type checking and memory usage correctness there is even less need for a debugger in the style of GDB.

That and the fact that it is so easy to write and run tests for ones Rust modules.

4 Likes

rust-gdb is installed by rustup (I’m not sure how to check which component or whether it’s part of the default rustup install). You need to have the distribution’s GDB installed too.

1 Like

I’m mostly in the same boat, but having previously worked for a company that makes a debugging front-end for supercomputers (100000+ threads/processes running concurrently) gave me a new appreciation of the usefulness of debugging tools.

For me the problem is that in “normal” code, I rarely need anything more that few well-placed dbg! calls, so I’ve never got used to using command-line debuggers like GDB. Without that familiarity, figuring out how to use them effectively to solve my problem is usually a bigger problem than the bug itself. With greater familiarity or better front-end tooling, I’d probably find debugging tools much more useful.

6 Likes

If you use VSCode the CodeLLDB plugin works well and supports Rust breakpoints and symbols, etc. I was suprised how easy it was to setup:

5 Likes

As several others have written, Rust has an interesting way of not requiring a debugger in the same way you may be used to from other languages.

With that said:

  • I've had to resort to using a debugger a few times. I've used rust-lldb for local debugging and think it works good.
  • One recurring situation where I need a debugger is to remotely debug Windows services. If you need to do this you can connect the Visual Studio debugger to a remote instance of msvsmon and debug Rust executables; though it's not excellent at handling complex data types.
3 Likes

I have never found a debugger useful for tracking down memory or concurrency bugs, but they do help me figure out the cause of logic errors.

7 Likes

I believe the actual question of what debuggers are available has been answered. But as others have said, whether you actually need a debugger at all depends very much on the type of code you are writing. They do have their use case, but I have personally never needed to use one, and for a lot of code, it is much easier to use println!, unit tests or other techniques to find the problem. And of course, most of the time if it compiles it works and most of my time is spent getting it to compile.

1 Like

If you need to do this you can connect the Visual Studio debugger to a remote instance of msvsmon and debug Rust executables; though it's not excellent at handling complex data types.

Hi @blonk, this is an area the Rust team at Microsoft is working on improving (see for example #85292, #85269 and #83941). If you see this again, please consider filing a bug report so we can take a look at it.

Thanks!

2 Likes

I have found gdb to work pretty well on linux for rust binaries. The code is formatted correctly. I have also found that whatever debugger vscode uses on linux works well. But you have to manually run cargo build before launching the debugger for both gdb and the windows debugger.

I feel differently about debuggers than others posters here apparently. I think they are an invaluable tool and are part of my code development process. When writing non trivial code, I'll write a block of code then single step through it in the debugger, following different code paths, looking at intermediate results of tricky algorithms etc. to make sure the code is actually doing what I want it to be doing. Not only do I find errors earlier this way, I often realize that I've overlooked a border case.

For me, simple print messages are too coarse as a first pass correctness check, except in simple cases.

In some ways, I think my approach of "debug as you go" is similar to the mindset of "write tests first"

I think you are right. Although I'm not so fanatical about the "write tests first" TDD commandments.

An important difference to my mind is that if one writes tests one has something that can be easily run and rerun, over and over, as development progresses. If someone else gets to work on the code and they make changes they have some confidence in it's correctness. Or at least find out what they broke pretty quickly.

Whereas if one just steps through with a debugger one has has only satisfied oneself that things are correct at that particular time. If anything changes and one has to do it all over again. Would that new developer know what to look for when they make changes?

So it's a preference to automate things rather than doing the manual work.

1 Like

Agreed. I do a debugger walk through to find obvious bugs and to assure myself of initial code correctness , but then tests should be developed for future checking.

In my perosnal experience there have been very many times where I couldn't use a debugger because of oddities of my development workflow ( sometimes I have to do dev in a container because I'm not root on my development machine ) or the fact that I was working on a DevOps automation tool that could only be tested in a specific environment after being deployed to a remote machine.

In these cases, I had wanted a debugger sometimes, but print lines had to suffice and worked pretty well in many cases.

The interesting thing is that the times that I have had access to a debugger and thought it would help me out, it didn't help me half as much as I thought because all of the tricky things/algorithms in code for me have happened to be in hot loops. In these cases, it often doesn't help if I have to step through every loop when the loop is going to run 10000 times before I run into an issue. But using println I can actually get a dense aggregation of all of the variables I'm intersted in and scan that info quickly in a log to see how it changes over time. So having a printed history was more useful than an interactive walkthough.

Still, that isn't every case. There was one time I was debugging an FFI call and I was able to see that the memory that one of my variables was pointing to was blank and it helped me realize that I had accidentally gotten the order of the arguments of the C function wrong. Very useful.

So for me it depends a lot on what kind of software I'm working on.

Well there is the thing. On the rare occasions I have been so stumped by a bug that I felt the urge to reach for a debugger it ended up being of no use.

A typical example is trying to find some race condition in multi-threaded code. Start stepping through a thread and it can hide the problem. Try to find where things go wrong with data corruption, no chance, the problem shows up in some thread millions of instructions after some other thread has cause the corruption.

A classic case, years ago, was trying to debug why my x86 boot code failed when transitioning from 16 to 32 bit mode on the new fangled i386 chip. Turned out it was the Intel i386 In circuit Emulator I was using that was getting confused at that point.

Nope, it's modern day thread and address sanitiser tools for me when using C/C++.

Or just save a lot of grief and use Rust :slight_smile:

No, Rust support has been in upstream GDB for several years now, and any reasonably recent distro will ship a Rust-enabled version. You do not need a fork. The rust-gdb wrapper sets some paths to enable some Python pretty-printers specific to the Rust standard library. If you use ordinary gdb most things will still work fine.

2 Likes

Debugging rust is hard with all the auto derefs and whatnot. Debugging async rust code is a whole new hell, as I've learned over the last week. It definitely changed my impression of rust's stack depth. Anyway the point is there is definitely room for improvement in the tooling beyond "rust has type-helper wrappers for lldb and gdb so we're good". While rust technically works fine with gdb and lldb, rust is missing a lot of support for practically and effectively using those tools in anything more than trivial scenarios. For example, try inspecting a hashmap in the debugger or stepping through an await.