0

I am debugging in a recompile-debug cycle that looks as follows:

  • Compile binary
  • Run debugger gdb prog
  • Find an error and fix the source
  • Exit debugger with pressing ctrl+d or typing quit

I would like to add Valgrind in the workflow to break as soon as I faced incorrect out-of-range memory read or write. I found that if I follow the officially documented process of running Valgrind with gdb I have to perform a lot more time-consuming steps.

  • Compile binary
  • Run valgrind valgrind --vgdb=yes --vgdb-error=0 prog
  • Open new terminal window and type gdb prog
  • Run target remote | vgdb (or, even worse, copy-paste command for connection printed in valgrind window if I am running multiple debug sessions)
  • Find an error and fix the source
  • Exit debugger
  • Kill application with valgrind process with kill -9 (because Valgrind doesn't stops it on gdb exit)

How I can automate these 3 extra steps? Ideally, I would expect to have a command like mygdb as a drop-in replacement for gdb that runs Valgrind under the hood, maybe debug slower, but breaks as soon as Valgrind detects an error.

Curious
  • 507
  • 3
  • 16

2 Answers2

1

--vgdb-error=0 indicates to valgrind to stop before it starts executing your program, so that you can connect with GDB and e.g. put breakpoints.

But if you only want to debug once an error is detected, rather give --vgdb-error=1.

With this, as long as valgrind reports no error, there is no need to do the 3 steps in bold, as valgrind will run your program till the end and exit.

When valgrind stops when encountering an error, you have to start a gdb. You could write a shell script to automate part of the other commands e.g.

gdb -ex 'target remote | vgdb'

This script can extract the vgdb command from a log file output or any other way.

You could also define in your .gdbinit a command such as

define vquit
  kill
  quit
end

and use vquit instead of quit.

You can also define a gdb command to directly start your application under valgrind and connect gdb to it, e.g. something like:

define vrun
  shell valgrind --vgdb-error=0 $arg0 &
  target remote | vgdb --wait=10
  continue
end

and then inside gdb, you can do:

(gdb) vrun your_application
phd
  • 3,669
  • 1
  • 11
  • 12
  • "as long as valgrind reports no error" this probably never happens since I would not use Valgrind at all in that case. Is it possible to override `ctrl+d` with `vquit` as well? – Curious May 20 '21 at 17:13
  • It would also be nice to avoid opening a separate window for gdb. – Curious May 20 '21 at 17:17
  • Edited the answer to provide a "vrun" gdb user defined function to start and debug from a single window. Of course, you might want to extend the way you start your application, such as redirecting the output and/or input. – phd May 20 '21 at 17:48
0

How I can automate these 3 extra steps?

Not a direct answer to your question, but your entire approach is likely wrong.

You should not use the debugger to tell you about bugs; use unit tests instead. Your cycle should be make && make check.

It also helps to write the test before implementing any new functionality (see test-driven development). The test will fail, and then you'll make it succeed by implementing the new feature.

In addition, you should get into the habit of running all of your tests with the Address and Memory Sanitizers (which together catch many more bugs than valgrind does).

Finally, valgrind report itself usually provides sufficient info to understand the bug. Valgrind's integration with GDB is there for rare cases where the error report is hard to understand without looking at the values of locals, parameters, etc.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362