2. 1981
Debugging n.
Removing a BUG, either by tinkering with the
program or by amending the program specification so that the side effect of the bug is
published as a desirable feature. See also:
KLUDGE; ONE-LINE PATCH; STEPWISE REFINEMENT.
- Stan Kelley-Bootle
The Devil's D.P. Dictionary
4. 1949
As soon as we started programming, we found to
our surprise that it wasn't as easy to get
programs right as we had thought. Debugging
had to be discovered. I can remember the exact
instant when I realized that a large part of my
life from then on was going to be spent in
finding mistakes in my own programs.
- Maurice Wilkes
5. 1974
Debugging is twice as hard as writing the code
in the first place. Therefore, if you write the
code as cleverly as possible, you are, by
definition, not smart enough to debug it.
- Brian W. Kernighan and P. J. Plauger
The Elements of Programming Style
6. The crucial debugging insight:
Q: Why are you debugging to begin with ?
A: Because you are not a perfect programmer
8. ”Option” doesn't mean its optional
If you don't use -Wall -Werror by default,
your code sucks by default.
Also consider:
-Wstrict-prototypes
-Wpointer-arith
-Wcast-qual
-Wswitch
-Wcast-align
-Wchar-subscripts
-Wnested-externs
-Wformat
-Wno-missing-field-initializers
-Wmissing-prototypes
-Wreturn-type
-Wwrite-strings
-Wshadow
-Wunused-parameter
-Winline
-Wredundant-decls
-Wextra
-Wno-sign-compare
9. Get a second, third & fourth opinion
* Use multiple compilers (LLVM vs. GCC)
* lint(1)
* FlexeLint ($1k)
* Coverity
* LLVM's static analysis tools
* Different CPU/endianess/word-size
10. Random FlexeLint example:
if (!(dfu_root->flags |= DFU_IFF_DFU))
main.c 483 Info 820: Boolean test of a parenthesized assignment
main.c 483 Info 774: Boolean within 'if' always evaluates to False
[Reference: file main.c: line 483]
main.c 483 Info 831: Reference cited in prior message
11. 1979
The most effective debugging tool is still careful
thought, coupled with judiciously placed print
statements.
- Brian W. Kernighan
Unix for Beginners
12. 2013
It's even easier to let the program just tell you
where the bugs are.
- Poul-Henning Kamp
13. Proactively eliminate doubt
#include <assert.h>
if (*q != '0' && r == e) {
if (b != vep->tag) {
l = e - b;
assert(l < sizeof vep->tag);
memmove(vep->tag, b, l);
vep->tag_i = l;
}
return (NULL);
}
14. Performance price List
●
●
●
●
●
●
●
●
char *p += 5;
strlen(p);
memcpy(p, q, l);
Locking
System Call
Context Switch
Disk Access
Filesystem
10-9s
CPU
Memory
Protection
10-1s
Mechanical
15. What does assert() actually do ?
#define assert(e) ((e) ? (void)0 : __assert(
__func__, __FILE__, __LINE__, #e))
void
__assert(const char *func, const char *file, int line,
const char *failedexpr)
{
}
(void)fprintf(stderr, "Assertion failed: ”
”(%s), function %s, file %s, line %d.n",
failedexpr, func, file, line);
abort();
/* NOTREACHED */
16. Make your own asserts
#define AZ(foo)
do {assert((foo) ==
#define AN(foo)
do {assert((foo) !=
#define XXXAZ(foo) do {xxxassert((foo)
#define XXXAN(foo) do {xxxassert((foo)
#define WRONG(expl) [...]
#define INCOMPLETE(expl) [...]
#define Lck_AssertHeld() [...]
void WS_Assert(...);
void MPL_Assert_Sane(...);
void VTCP_Assert(...);
...
0);} while (0)
0);} while (0)
== 0);} while (0)
!= 0);} while (0)
17. If it can't happen, assert that
AZ(pipe(vwe->pipes));
AZ(shutdown(sock, SHUT_WR));
AZ(close(fd));
AZ(fstatvfs(fd, &fsst));
AZ(pthread_mutex_lock(&vsm_mtx));
...
XXXAZ(unlink(vp->fname));
XXXAZ(setgid(mgt_param.gid));
...
sto = calloc(sizeof *sto, 1);
XXXAN(sto);
...
18. Assert the locking situation
static void
ban_reload(const uint8_t *ban, unsigned len)
{
struct ban *b, *b2;
int duplicate = 0;
double t0, t1, t2 = 9e99;
ASSERT_CLI();
Lck_AssertHeld(&ban_mtx);
24. How ?
Use pthread_setspecific(3) to tie state to thread
In your __assert() function:
Use pthread_getspecific(3) to get that state
See also backtrace(3) API (OS/Compiler dependent.)
25. Test that your code works
Automate running of your test-cases
I mean, you do have test-cases ?
right ?
Right ?!
27. Varnish testing
336 VTC testcases in 11 categories
Important category:
Regression tests for bugs
”make check” runs test-cases (~ 10 minutes)
Jenkins tinderbox builds/tests ~10 platforms
gcov(1) used to monitor test-coverage. (89%!)
28. Preventive Debugging Summary
* Code defensively
* Use tools to improve your code & coding
* Assert() that you know what's going on
* Fail ASAP.
* Dump useful info while you can
* Know that your code works & can be executed
29. Does that work ?
Yes!
Varnish delivers a LOT of web-pages
We get approx 1 crash report every 2-3 weeks
We almost never need gdb(1)
30. 1946
Intet tab bør ramme os, som kan undgås
ved rettidig omhu.
- Skibsreder A.P. Møller