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
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, I can see the above output on a high file descriptor even if
the descriptor isn’t actually open; the syscall still happens and
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
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.