So, you’re having trouble with your program? Now’s a good time to jump into debugging!
Technique 1: Printf Debugging
Sometimes, the simplest methods are the best. Printf debugging simply means putting a printf call somewhere in your code, to print out the value of a variable or set of variables. It can also be used to deduce the order of function calls, or count how often a section of code is being called. It’s a versatile but simple tool in our bag of debugging tricks.
Upsides of printf debugging:
easy/quick method that only exists in code
can write messages to provide context to the output
easier to review a large amount of output/data at once (like printing information inside a loop)
don’t need to learn a specific debugger (MSVC, gdb, etc)
Downsides of printf debugging:
code/calculations are particularly complex may not lend themselves well to printf debugging
in (very) large projects, recompiling the code can be prohibitive
tracking where to add/remove printf calls can be tedious and error-prone
The simplest way to go about debugging with printf is to put a call to printf in a section of code where you’d like to diagnose an issue. Consider the following (contrived) example, where we want to calculate the sum of numbers between 1 and 5, inclusive:
//We want to know the sum of the numbers //between 1 and 5, inclusive int sum = 0; for (int i = 0; i < 5; ++i) { sum += i; } printf("Sum of numbers 1 to 5: %d", sum);
Output:
Sum of numbers 1 to 5: 10
Whelp, that isn’t correct! We were expecting 1+2+3+4+5, which is 15. So where did we go wrong?
We can insert a print statement into our loop to see what’s happening:
//We want to know the sum of the numbers //between 1 and 5, inclusive int sum = 0; for (int i = 0; i < 5; ++i) { printf("Previous sum: %d | Adding to sum: %d | ", sum, i); sum += i; printf("Current sum: %d\n", sum); } printf("Sum of numbers 1 to 5: %d", sum);
Output:
Previous sum: 0 | Adding to sum: 0 | Current sum: 0
Previous sum: 0 | Adding to sum: 1 | Current sum: 1
Previous sum: 1 | Adding to sum: 2 | Current sum: 3
Previous sum: 3 | Adding to sum: 3 | Current sum: 6
Previous sum: 6 | Adding to sum: 4 | Current sum: 10
Sum of numbers 1 to 5: 10
Now we can see what we’re doing at each step of our loop, which illuminated the issue: we’re adding the numbers 0 to 4 inclusive, not 1 to 5. Now we can remove our print statements and fix our error:
//We want to know the sum of the numbers //between 1 and 5, inclusive int sum = 0; for (int i = 1; i <= 5; ++i) { sum += i; } printf("Sum of numbers 1 to 5: %d", sum);
Output:
Sum of numbers 1 to 5: 15
Technique 2: Using the MSVC Debugger
The MSVC debugger is a powerful tool for tracking down bugs and inspecting your code as it runs. Certain kinds of bugs may be easier to diagnose using the debugger, as opposed to printf debugging. This note barely scratches the surface of the MSVC debugger’s capabilities, but we’ll go over the basics to get you started.
OPEN AND READ THIS BEFORE STARTING!
To debug your code in MSVC, you MUST compile your code using the MSVC debug flag. This creates what’s known as a Program Database File, which stores debugging information about your code. Without a PDB file, you cannot debug your program in the MSVC debugger.
Normally, your compile step might look like this:
cls MyCode.c
You will need to add the -Zi flag to your compliation, like so:
cls -Zi MyCode.c
You should be able to see /debug in the output below:
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29913 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
MyCode.c
Microsoft (R) Incremental Linker Version 14.28.29913.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:MyCode.exe
/debug <----------------THIS SHOWS THAT YOU BUILT WITH THE DEBUG FLAG!
MyCode.obj
You can also check the Solution Explorer in Visual Studio, or just open your folder in Windows to see your new .pdb file:
Setting Breakpoints
Breakpoints allow you to stop the execution of your code while it is running. This is useful for inspecting the values of certain variables or formulas in real-time as the code is running, and to catch bugs that might be trickier or impossible to catch via printf debugging.
There are two ways to add new breakpoints to your code: you can either click in the margin to the left of your code, or you can press F9 to add or remove a breakpoint from the current line (where your typing caret is). Using Ctrl+F9 or right-clicking the breakpoint and selecting “Disable Breakpoint” will disable the breakpoint, making it inactive but leaving it on its current line (this is a convenience to ensure you don’t forget where a breakpoint might have existed previously).
(A breakpoint added to code)
(Context menu for deleting or disabling breakpoints)