COMP10002 Foundations of Algorithms

Checking And Debugging Your C Code

Practical commands for compiling with strong warnings, checking your code for bugs, and using tools that help you catch mistakes before submission.

Baseline build

Work from the directory that contains your own a1.c.

The safest starting point is to compile with the same warning level and language mode used by the assignment:

clang -Wall -Wextra -Wno-newline-eof -Wno-unused-parameter \
  -pedantic -std=c17 -o a1 a1.c -lm

This is a good default because it is close to what the autograder expects. If your code does not compile cleanly here, fix that first.

Why first-year students should use these tools

If you are new to C, these tools are helpful because many C mistakes do not produce neat, obvious error messages.

A compiler might reject your code completely, but it can also accept code that still has a bug in it. Extra warnings , static analysis , and sanitizers give you more chances to catch problems early.

That matters in first year because:

For this assignment, these tools are especially useful for finding:

What “static analysis” means

When you compile a C program, the compiler already checks some things for you, such as syntax errors and some suspicious code patterns.

Static analysis means:

For this assignment, it helps to separate three kinds of tools:

These tools are useful, but they are not magic. A warning may be a false alarm, and a clean report does not prove the program is correct.

Clang flags

If you want a stricter local Clang build, try:

clang -Wall -Wextra -Wshadow -Wconversion -Wdouble-promotion \
  -Wformat=2 -Wstrict-prototypes -pedantic -std=c17 -o a1 a1.c -lm

These flags can help catch:

While you are still filling in the scaffold, you may also see unused-parameter warnings from unfinished TODO functions. That is normal in incomplete code. Once the functions are implemented, many of those warnings disappear.

Not every warning here must be enabled for grading, but they are useful while cleaning up your code.

Clang also includes a built-in static analyzer:

clang --analyze -Wall -Wextra -pedantic -std=c17 a1.c

If it reports a possible null dereference , dead store , or suspicious path , inspect it carefully. Some reports are false positives , but many are worth fixing.

GCC flags

On Linux with a real GNU gcc, a comparable warning build is:

gcc -Wall -Wextra -Wshadow -Wconversion -Wformat=2 \
  -Wstrict-prototypes -pedantic -std=c17 -o a1 a1.c -lm

Recent GCC versions also have an analyzer mode:

gcc -fanalyzer -Wall -Wextra -pedantic -std=c17 -o a1 a1.c -lm

Important note: on many macOS setups, gcc is actually Apple Clang in disguise. If gcc --version prints something like Apple clang, then -fanalyzer is not the GNU GCC analyzer and may not exist. In that case, use clang --analyze and cppcheck instead.

Checking tools

cppcheck

cppcheck is available in many lab or Homebrew-style environments and is installed in this local environment. A practical command is:

cppcheck --enable=warning,style,performance,portability \
  --std=c17 --language=c --inline-suppr a1.c

If you want more detail, add:

cppcheck --enable=all --std=c17 --language=c --inline-suppr a1.c

cppcheck is especially useful for:

It can also be noisy, so treat it as a review tool, not an oracle.

Clang static analyzer

If you are using Clang, this is the simplest built-in static-analysis pass:

clang --analyze -Wall -Wextra -pedantic -std=c17 a1.c

This is path-sensitive , so it sometimes catches issues that ordinary warning flags miss.

Runtime tools

Strict warnings and static analysis help, but runtime tools catch a different class of bugs.

A sanitizer is a runtime checking tool. You compile your program with extra instrumentation, then run it normally. If something dangerous happens while the program is executing, the sanitizer tries to stop immediately and explain the problem.

The most useful sanitizers for this assignment are:

AddressSanitizer on its own is already very useful:

clang -g -fsanitize=address -fno-omit-frame-pointer \
  -std=c17 -o a1-asan a1.c -lm
./a1-asan < test_data/test0.txt

If your program reads or writes outside an array, uses freed memory, or corrupts the stack, AddressSanitizer tends to gives a much better explanation than a normal crash.

A good general-purpose local debug build is:

clang -g -fsanitize=address,undefined -fno-omit-frame-pointer \
  -std=c17 -o a1-sanitize a1.c -lm
./a1-sanitize < test_data/test0.txt

If you are using dynamic allocation and specifically want leak checking, you can also try:

clang -g -fsanitize=address,undefined,leak -fno-omit-frame-pointer \
  -std=c17 -o a1-sanitize a1.c -lm

Suggested workflow

For this assignment, a sensible local checking loop is:

  1. Compile with the baseline assignment command.
  2. Recompile with a stricter warning set.
  3. Run cppcheck if available.
  4. Run clang --analyze if you are using Clang.
  5. Run an AddressSanitizer build if something is crashing or behaving strangely.

No single tool is enough by itself. The goal is to combine fast compiler feedback, course-specific style checks, and at least one analyzer that looks for suspicious code paths.