a breakpoint
Imagine reading a long set of assembly instructions for furniture and sticking a bright tab on step 12 that says 'STOP HERE and check what you have built so far'. A breakpoint is exactly that tab, but for a running program: a marker you place on a particular line or function that tells the debugger 'pause the program right here, before this runs, and hand control back to me'. Instead of the program rushing past, it freezes at that spot so you can look around.
Concretely, you set a breakpoint by location: a source line ('break buggy.c:42'), a function name ('break compute'), or even a raw address. When you then run the program, it executes normally at full speed until it is about to run that line - then it stops, and the debugger tells you which breakpoint hit and where you are. Now the program is frozen but fully intact: you can print variables, look at the call stack, change values, then continue. Under the hood the debugger typically does this by replacing the instruction at that address with a special trap instruction; when the CPU hits it, it traps into the operating system, which notifies the debugger. The debugger then quietly puts the original instruction back so you do not notice the swap.
Why it matters: breakpoints are the most basic way to inspect a program at a chosen moment without drowning in output. The skill is choosing where to put them - not on every line, but at the boundary where you suspect things first go wrong, so you can check 'were the inputs already bad when we got here, or did this function break them?'. A common refinement is to make a breakpoint fire only under a condition (a conditional breakpoint) so you stop on the one iteration that matters rather than all million. A breakpoint on a line that never runs simply never triggers - which is itself a useful clue that your code path is not what you assumed.
In gdb: break compute sets a breakpoint at the start of function compute. Then run executes until compute is first called, where it stops and prints the line; from there you can print n to see the argument. In lldb the command is breakpoint set --name compute.
Set a breakpoint at a function, run, and stop the instant that function is first entered.
A breakpoint pauses before the line runs, not after - so its variables show the state on entry to that line, not its result. If your line never breaks, the bug may be that the code path you expected is not actually taken.