UPI Study › Courses › C++ Programming › Free lessons › Lesson 5.7 Free with a free account
Avoiding Loop Traps and Debugging
C++ Programming · Chapter 5: IterationSection 5.7 · lesson 35 of 84video coming soon
← break, continue, and Other Flow ControlsNext lesson: Real-World Repetition Scenarios →
In this lesson
Infinite loops, boundary errors, and debugging strategies.
- Name the 4 causes of a loop that never ends
- Never compare accumulated fractions for equality
- Settle boundaries with 3 written values
- Watch a loop run, with a debugger or printed tracing
Transcript
Everything said in the video, section by section (1,714 words). Read along, or search it.
Opening Idea
Quiet Loop Faults and How to Find Them
Loop faults are quiet. A loop that never ends doesn't complain, and a loop that repeats one time too many produces an answer that looks entirely reasonable. Both are found by the same method: form a precise expectation, then watch what actually happens. This lesson covers the handful of causes behind almost every runaway loop, and a systematic way to settle boundary questions. And it covers two tools for watching a program run: a debugger, and printed output.
Two Families
Never Stops Versus Stops Wrongly
Everything that goes wrong with a loop belongs to one of two families. Telling them apart before you investigate saves most of the time. The first family is, it never stops. The program sits there, possibly printing forever, possibly printing nothing while the fan spins up. There's no error message, because nothing illegal has happened. The second family is, it stops in the wrong place: one pass too many, one too few, or none at all. This one is more dangerous. The program finishes normally, and hands you a wrong answer with no sign that anything happened.
Cause One
Nothing Changes the Tested Value
A loop ends when its condition becomes false. So a loop that never ends has a condition that can never become false, and there are only so many ways to arrange that. One: nothing changes the value the condition tests. Here, count starts at 5, and the loop runs while it's above 0. But nothing ever reduces it. The obvious version is an update that was simply forgotten. The version that catches people is an update that sits inside a decision that doesn't always run. Or one that changes a different variable.
Quick Check
Does the Step-by-Two Loop Stop?
Here's a loop that counts in steps. It starts at 1, adds 2 each time, and continues while i is not equal to 10. Quick check: does it stop? Pause, and trace it.
Cause Two
A Comparison That Can Never Be Satisfied
No. The counter takes 1, 3, 5, 7, 9, 11, 13, and steps straight over 10 without ever being equal to it. That's cause two: a comparison that can never be satisfied. That's why less-than and less-than-or-equal are safer bounds than not-equal, whenever the step isn't one. A comparison asks, have we passed it yet. An equality test asks, did we land on it exactly. And a loop that misses its target once misses it forever.
Cause Three
Fractions Never Land Exactly on Target
Three: fractional values that never land where you expect. This loop starts x at 0, adds 0.1 each time, and continues while x isn't 1.0. It's the same fault as the last one, hiding. The value 0.1 can't be represented exactly in the binary form the machine stores. So every addition carries a tiny error, and the errors accumulate. After ten additions, the value is a fraction away from 1. It prints as 1, but it compares as not equal, and the loop sails on past. The rule that follows: never test fractional values for equality. The repair is to count with whole numbers, for n from 0 while n is less than 10, and derive the fraction inside the body: n over 10.0.
Cause Four
One Equals Sign Instead of Two
Four: one equals sign where two were meant. While choice equals 1, written with a single equals sign, runs forever, whatever the person types. A single equals sign assigns. It puts 1 into choice, and hands the value 1 back to the condition. Any non-zero value counts as true. So the condition is true permanently, and the variable is overwritten on every pass. Clang warns about it even by default, and other compilers do once warnings are switched on. And reading the line aloud catches it too: while choice becomes 1 is plainly not what was meant.
Recap
Four Causes and Their Confirming Signs
Here are the four causes together, each with the observation that confirms it. If the tested value never changes, the output repeats identically, or nothing appears. Watch the condition variable: it holds the same value every pass. If the comparison can't be satisfied, the counter runs past the bound. Use less-than or less-than-or-equal whenever the step isn't one. With fractions, the printed values look correct all the way through. Print many decimal places, and count in whole numbers. And an assignment written as a comparison runs forever regardless of input. Read it aloud, and turn warnings on.
Boundary Method
Three Values Settle the Comparison
The second family of fault is decided by a single character: less-than, or less-than-or-equal. Arguing about it in the abstract is unreliable. So write down three concrete values, before you choose. The first value wanted, the last value wanted, and the first value not wanted. For the months of a year, that's 1, 12, and 13. Start from 1. Then pick the comparison that stops the loop between the last wanted value and the first unwanted one, and check it against both. 12 is at most 12: true, so the last wanted month runs. 13 is at most 12: false, so the loop stops. Both checks pass, so the header is right.
Header Examples
Common Intents and Their Pass Counts
Here are common intents, with the header each needs. The numbers 1 to 12: start at 1, continue while i is at most 12. Twelve passes. Ten repetitions counting from 0: continue while i is less than 10. Nine passes the check, and ten fails it. Every second number from 0 to 20 inclusive is 11 passes. Counting down from 10 to 1 is 10 passes. And a loop that should do nothing when the limit is 0 fails its very first test. Almost everybody checks that the last wanted value runs. Far fewer check that the first unwanted value doesn't. That's why an off-by-one at the top end survives casual testing.
Debugger Tools
Breakpoints, Stepping, and Watch Expressions
A debugger runs your program while letting you stop it, look at every value, and advance it one step at a time. A breakpoint marks a line where execution stops. Put one on the first line inside the body, and look at the counter each time it stops. A conditional breakpoint stops only when a condition you supply is true. Stop when i equals 97, rather than pressing continue 96 times. Step over runs the current line and stops on the next. Step into does the same, but if the line calls something you wrote, it stops inside it. A watch expression keeps a value visible as you step. Watch the loop's condition itself: seeing it stay true confirms a runaway loop. The highlighted line is about to run, not yet run. A debugger doesn't find faults. It shows you what's happening, and finding the fault is still your job.
Runaway Loops
Interrupt First, Then Inspect the Watch
A loop that never ends can't be stepped through, because it never reaches the line after it. So interrupt the program first, with the debugger's pause control, or the interrupt key in a terminal, and look at where it stopped. It'll be inside the loop, and the watch pane will show a condition that's true, and a variable that isn't moving. That single observation identifies the cause from the four, nearly every time.
Printed Tracing
Choosing What to Print in a Loop
Printed tracing is the older technique, and it isn't a lesser one. It works everywhere, and it leaves a record you can read twice. The skill is in choosing what to print, because a loop that prints one useless line per pass buries the evidence. Print every variable the condition depends on, not just the counter. A loop testing i at most limit can misbehave because limit isn't what you assumed. Mark the lines with a trace tag, so they can be filtered from real output. And print at the top of the body, so the values shown are the ones the condition was just tested against.
Tracing Guide
Matching Printed Output to Symptoms
What to print depends on what you're seeing. If it runs forever, print the counter and the whole condition each pass. That shows whether it's stuck, or moving but never satisfying the comparison. If it runs zero times, print both sides of the condition once, just before the loop. Almost always, the bound is smaller than the start value. If it's one pass off, print the counter at the top of the body, and again after the loop. And if the total is wrong but the count is right, print the total before and after the line that changes it. Then take the tracing out again. Trace lines are scaffolding. Left in, they clutter real output and confuse whoever reads it next.
Worked Example
Diagnosing the Endless Tenths Loop
Here's a diagnosis from start to finish. The report: it should print the ten tenths between 0 and 1, and it prints forever. Step one: which family? It never stops, so the condition never becomes false. That rules out every boundary question. Step two: a hypothesis. The counter is clearly changing, since different values print. That leaves a comparison that can't be satisfied: an equality test on a fraction. Step three: one observation. Watch x minus 1.0. Around the tenth pass, it's a tiny non-zero number instead of zero. Confirmed. Step four: the repair. Count in whole numbers, and produce the fraction inside the body. Step five: check the boundaries. N below 10 gives 0.0 through 0.9. If 1.0 was meant too, n at most 10, and 11 passes.
Observation
Seventeen Digits Reveal the Hidden Error
Here's that observation, printed. After ten additions, x prints as 1, but with 17 digits it shows 0.99999999999999989. And equality with 1.0 is false.
Key Terms
Vocabulary for Loops and Debugging
A few key terms. An infinite loop is one whose condition can never become false, so it repeats until stopped from outside. A boundary error is a fault at the first or last value of a range, usually one pass too many or too few. A debugger runs a program so it can be paused, inspected and stepped. A watch expression is a value it keeps visible. And printed tracing means temporary output statements that record values as the program runs.
Summary and Challenge
Review and the Five to Fifteen Puzzle
To summarize. A runaway loop has a value that never changes, a target it can't land on, a fractional comparison, or an assignment where a comparison was meant. Settle boundaries with three values, and check both ends. Debug with breakpoints and a watch on the condition, or trace every variable the condition uses, and remove the tracing afterward. Here's something to think about. You want the numbers 5 to 15 inclusive. Apply the three-value method: what's the header, and how many passes? The first wanted is 5, the last wanted is 15, and the first unwanted is 16. So i from 5, while i is at most 15: 11 passes.
About C++ Programming at UPI Study
C++ Programming (Computer Science 242) is a self-paced online course of 84 video lessons in 11 chapters, from your first program to decisions, loops, arrays, functions, classes, files, pointers and inheritance. It carries a NCCRS credit recommendation for 3 semester credits.
Every lesson transcript is free on pages like this one, and the videos are free with a free UPI Study account. Enrolling adds a practice quiz after each lesson, the graded work and final exam that earn the credit, lifetime access, and an official transcript on completion. UPI Study has helped over 130,000 students with college credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.
Enroll now → Course details Download the syllabus Every course with PRO →
Why take it here
Why students take C++ Programming with UPI Study
Where the credit goes
Universities that work with NCCRS
C++ Programming carries a NCCRS credit recommendation. These universities work with NCCRS; some are UPI Study's signed partners. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.
Thomas Edison State UniversitySigned partner
University of the PeopleSigned partner
Charter Oak State CollegeSigned partner
Strayer UniversitySigned partner
Columbia Southern UniversitySigned partner
Indiana TechSigned partner
Penn StateWorks with NCCRS
Southern New Hampshire UniversityWorks with NCCRS
SUNYWorks with NCCRS
+many more cooperating universitiesFind my college →Find my college → Not listed? Ask Athena in the corner of this page, or book a 15-minute call.
FAQ
Questions students ask us
About Avoiding Loop Traps and Debugging
What are the 4 causes of an infinite loop in C++?
Why shouldn't I compare floating-point numbers for equality in a loop condition?
How do I decide between less-than and less-than-or-equal in a loop condition?
How can I debug a loop that runs forever using a debugger or print statements?
About the C++ Programming course
How many college credits is C++ Programming?
How much does C++ Programming cost and what is included?
Which universities accept UPI Study credits?
How long does C++ Programming take?
How are the exams done?
How do my credits reach my college?
Ready for the full course? Earn 3 credits in C++ Programming.
84 video lessons, a quiz after each one, and the graded work that earns the credit. Recommended for credit by NCCRS.
3 credits · NCCRSEnroll →