Skip to content
📖 Auto vs The Little Book of CBook contents

Chapter 7: Debugging, Testing, Profiling ​

Sections 71--80 C's debugging tools are powerful but manual. Auto aims to prevent bugs before they happen.

Debugging is where C and Auto diverge most dramatically. C programs can have subtle memory bugs that only appear under specific conditions. Tools like gdb and valgrind exist because C's lack of safety guarantees makes them necessary.

Auto prevents many of these bugs at the language level. When bugs do occur, Auto's testing framework and assertions help catch them early. This chapter covers both the C tools you should know about and Auto's built-in alternatives.


71. Debugging with GDB ​

GDB (GNU Debugger) is the standard C debugger. It lets you:

  • Set breakpoints to pause execution at a line
  • Step through code line by line
  • Inspect variables and memory
  • Examine the call stack
bash
$ gcc -g program.c -o program    # -g adds debug symbols
$ gdb ./program
(gdb) break main
(gdb) run
(gdb) next
(gdb) print x
(gdb) backtrace

GDB is powerful but has a steep learning curve. Most developers use it through a frontend like VS Code's debug adapter or a TUI interface.

Auto does not yet have a dedicated debugger, but since Auto transpiles to C, you can use GDB on the generated C code. The mapping is straightforward because Auto constructs translate directly to C equivalents.


72. Valgrind Memory Checking ​

Valgrind detects memory errors that compilers and runtime checks miss:

bash
$ valgrind --leak-check=full ./program
==1234== Invalid read of size 4
==1234==    at 0x400544: main (program.c:12)
==1234==  Address 0x5205054 is 0 bytes after a block of size 4 alloc'd

Valgrind catches:

  • Use after free
  • Buffer overflows (read and write)
  • Memory leaks
  • Uninitialized memory reads

Running Valgrind is slow -- your program runs 10-50x slower. It is typically used in CI pipelines or when tracking down a specific bug.

Auto makes Valgrind unnecessary for most cases because the language prevents these errors at compile time. Bounds checking, ownership tracking, and optional types eliminate the entire class of memory bugs that Valgrind detects.


73. Assertions ​

Assertions are runtime checks that verify a condition is true. If it fails, the program aborts with a message.

C assertions:

c
#include <assert.h>
assert(x > 0);                    /* Simple assertion */
assert(ptr != NULL && "ptr must not be null");  /* With message */

Auto assertions:

auto
assert(x > 0, "x must be positive")
assert(ptr != nil, "ptr must not be null")

Auto's assert includes a message parameter by convention, making it more informative than C's default assertion output. The transpiler maps this to C's assert() with the stringified condition.

Released under the MIT License.