Avoiding Loop Traps and Debugging | C++ Programming

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 →

Earn 3 college credits for C++ ProgrammingRecommended for credit by NCCRS · Computer Science 242 · self-paced · one payment, lifetime access

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.

Why take it here

Why students take C++ Programming with UPI Study

Your first real programming languageC++ teaches how programs really work: variables, control flow, functions, memory and objects. It is the base for data structures, algorithms, systems and game programming, and for most computer-science degrees.
Credit at a fraction of the priceThe same 3 credits can cost $750 or more at a US college. Here it is one payment, self-paced, with lifetime access.
Finish your degree soonerTransfer credits reduce the courses you still owe, so you can graduate earlier or lighten a heavy semester.
Strengthen an applicationA completed college-level course on an official transcript shows admissions and scholarship committees you can do the work.
Study on your own scheduleNo start dates, no deadlines. Watch the lessons, practice, and take the final when you are ready.
130,000+students helped with college creditsACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

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.

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++?
The four causes are: nothing changes the value the condition tests, a comparison that can never be satisfied (such as i != 10 when i steps by 2 from 1), fractional values that never land exactly on the target, and = written where == was meant. Each cause leaves a clue. For example, the condition variable holds the same value every pass, or the counter runs past the bound.
Why shouldn't I compare floating-point numbers for equality in a loop condition?
Fractions like 0.1 cannot be stored exactly in binary, so each addition adds a tiny error that accumulates. After ten additions of 0.1, x prints as 1 but holds about 0.99999999999999989, so x != 1.0 stays true and the loop runs past. Count with an integer n instead, and compute the fraction inside the body as n / 10.0.
How do I decide between less-than and less-than-or-equal in a loop condition?
Write down three values before choosing: the first value wanted, the last value wanted, and the first value not wanted. For months, those are 1, 12, and 13. Pick the comparison that is true for 12 and false for 13. Here, i <= 12 passes both checks. Many people test only the last wanted value, so also check that the first unwanted one stops the loop.
How can I debug a loop that runs forever using a debugger or print statements?
Interrupt the program first with the debugger's pause control or the terminal interrupt key, then look at the watch pane. A true condition and a variable that is not moving point to the cause. With printed tracing, print every variable the condition uses at the top of the loop body, mark the lines with a trace tag, and remove them afterward.

About the C++ Programming course

How many college credits is C++ Programming?
C++ Programming (Computer Science 242) carries a NCCRS credit recommendation for 3 semester credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.
How much does C++ Programming cost and what is included?
$250, paid once, with lifetime access: all 84 video lessons, a practice quiz after each, the graded work and final exam, and an official transcript when you finish. Students who want several courses choose UPI Study PRO instead.
Which universities accept UPI Study credits?
UPI Study has signed partner agreements with universities such as Thomas Edison State University, University of the People and Charter Oak State College, and works with universities such as Penn State, SNHU and SUNY. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities. Use "Find my college" on this page to check yours.
How long does C++ Programming take?
It is self-paced with no deadlines. The 84 lessons total about 0 hours of video; most students add reading and practice time and finish in a few weeks to a few months, on their own schedule.
How are the exams done?
Quizzes and assignments are online in the course. The final exam is taken online with proctoring; a person on the UPI Study team checks assignments, usually within two days.
How do my credits reach my college?
When the course shows 100% complete, request the official transcript from your dashboard. It is sent to the college you name, and you can send it to more than one. Check your college first with "Find my college" on this page, or ask Athena.

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.

C++ Programming
3 credits · NCCRS
Enroll →