Debugging is an essential skill for systems programming. This guide covers tools and techniques for finding and fixing bugs in your CSE320 assignments.
Always compile with debug mode when actively debugging:
# Clean build with debug symbols and debug output enabledmake clean debug
What debug mode enables:
-g flag: Includes debugging symbols (variable names, line numbers)
-DDEBUG macro: Activates debug() macro output
-DCOLOR macro: Colored terminal output
Message macros: -DERROR -DSUCCESS -DWARN -DINFO
Debug mode produces extra output that violates assignment specifications. Always do a final test with make clean all (non-debug mode) before submitting.
# Break at start of main(gdb) break main# Break at specific function(gdb) break png_read_chunk# Break at file:line(gdb) break png_reader.c:45
4
Run the Program
# Run with arguments(gdb) run -f tests/data/sample.png -s
Program will stop at your breakpoint.
5
Step Through Code
# Step to next line (steps into functions)(gdb) step# Next line (steps over functions)(gdb) next# Continue until next breakpoint(gdb) continue# Finish current function and return(gdb) finish
# Run programrun [args]# Step into function callsstep (or s)# Step over function callsnext (or n)# Continue executioncontinue (or c)# Finish current functionfinish# Run until line numberuntil 50
# Run in GDBgdb bin/png(gdb) run -f tests/data/sample.png -s# After crash:Program received signal SIGSEGV, Segmentation fault.0x0000555555555234 in png_read_chunk (fp=0x555555757260, out=0x0) at src/png_reader.c:6767 out->length = length;# Check backtrace(gdb) backtrace#0 0x0000555555555234 in png_read_chunk (fp=0x555555757260, out=0x0) at src/png_reader.c:67#1 0x0000555555555678 in main (argc=4, argv=0x7fffffffe0c8) at src/main.c:45# Inspect variables(gdb) print out$1 = (png_chunk_t *) 0x0# Problem: out is NULL!
Common segfault causes:
Null pointer dereference: out->length when out is NULL
Buffer overflow: Writing past end of allocated memory
Use-after-free: Accessing memory after free()
Stack overflow: Deep recursion or very large stack arrays
# Compile tests with debug symbolsmake clean debug# Run GDB on test suitegdb bin/png_tests# Set breakpoint in your function (not the test)(gdb) break png_read_chunk# Run specific test(gdb) run --filter=test_png_read_chunk# Debug as normal
==12345== HEAP SUMMARY:==12345== in use at exit: 768 bytes in 1 blocks==12345== total heap usage: 5 allocs, 4 frees, 1,500 bytes allocated==12345== ==12345== 768 bytes in 1 blocks are definitely lost in loss record 1 of 1==12345== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)==12345== by 0x108A45: png_parse_plte (png_chunks.c:78)==12345== by 0x108C12: main (main.c:102)
==12345== Invalid read of size 4==12345== at 0x108B67: png_read_chunk (png_reader.c:89)==12345== by 0x108D45: main (main.c:56)==12345== Address 0x5204044 is 4 bytes after a block of size 16 alloc'd==12345== at 0x4C2DB8F: malloc (vgpreload_memcheck-amd64-linux.so)==12345== by 0x108B12: png_read_chunk (png_reader.c:72)
What it means:
Reading 4 bytes past the end of a 16-byte buffer
Buffer allocated at line 72, invalid read at line 89
Fix: Check your buffer size calculations and loop bounds
==12345== Invalid read of size 1==12345== at 0x108C34: process_chunk (png_chunks.c:145)==12345== Address 0x5204040 is 0 bytes inside a block of size 13 free'd==12345== at 0x4C2EDEB: free (vgpreload_memcheck-amd64-linux.so)==12345== by 0x108BF2: png_free_chunk (png_reader.c:112)
What it means:
Trying to read memory that was already freed
Fix: Don’t use pointers after calling free(), or delay the free() call
# Full leak check with detailed infovalgrind --leak-check=full --show-leak-kinds=all --track-origins=yes bin/png -f test.png -s# Save output to filevalgrind --leak-check=full --log-file=valgrind.log bin/png -f test.png -s# Run with testsvalgrind --leak-check=full bin/png_tests --filter=test_parse_plte
# Display first part of PNG filehd tests/data/sample.png | head -20# Pipe to less for interactive viewinghd tests/data/sample.png | less# Show specific byte rangehd -s 0 -n 32 tests/data/sample.png # First 32 bytes
Symptom: Reading wrong data from file, EOF unexpectedlyDebug with ftell:
long pos = ftell(fp);debug("File position before read: %ld", pos);int result = fread(buffer, size, 1, fp);debug("Read result: %d", result);pos = ftell(fp);debug("File position after read: %ld", pos);if (result != 1) { if (feof(fp)) debug("EOF reached"); if (ferror(fp)) debug("Read error");}
// Temporary debug prints (remove before submission)fprintf(stderr, "DEBUG: chunk.length = %u\n", chunk.length);fprintf(stderr, "DEBUG: checkpoint reached at line %d\n", __LINE__);
#include <assert.h>assert(out != NULL && "Output pointer must not be NULL");assert(length <= MAX_CHUNK_SIZE && "Chunk length too large");assert(fp != NULL && "File pointer must be valid");