This post is not about any particular bug or bad programming practice, just a new “printf debugging” technique I came up with.
Often when tracking down a bug, it’s useful to add extra output to
track the state of the program in the moments leading up to the crash
or incorrect behavior, aka “printf debugging”. However, this technique
is “invasive” in the sense that it interleaves unwanted data into the
program output. Using stderr
instead of stdout
can alleviate the
problem to some extent, but when you’re inserting the debugging code
into a widely-used library (in my case, libc.so
) or a shell, even
having unwanted output on stderr
can be a problem.
A previous approach I had used was sending the output to an arbitrary
high file descriptor instead of stdout
or stderr
. For example,
dprintf(666, "message here");
This avoids breaking anything but a
program using a huge number of file descriptors, and allows reading
the output via adding 666>&2
to the command line.
However, let’s take that a bit further. I don’t really need the
program itself to print any output. I just need to be able to see the
message. Enter my other favorite debugging tool, strace
. Using
strace
, I can see the above output on a high file descriptor even if
the descriptor isn’t actually open; the syscall still happens and
returns with EBADF
. But there’s no reason it needed to be a valid
number that could be a file descriptor in the first place. I can
instead just use dprintf(-42, "message here\n");
and there’s no risk
of ever producing any output, but the strace
log (with the
appropriate options to increase string length limits) will show the
writes.
The result is a form of “printf debugging” that can safely be added in library code and other code that shouldn’t touch any file descriptors.