UPI Study › Courses › C++ Programming › Free lessons › Lesson 1.6 Free with a free account
The Build-Run-Fix Workflow
C++ Programming · Chapter 1: Foundations of ProgrammingSection 1.6 · lesson 6 of 84video coming soon
← Sequential Problem-SolvingNext lesson: How C++ Came to Be →
In this lesson
How software gets from idea to execution.
- Name the stages that turn source text into a program
- Explain why an object file can't run on its own
- Contrast compiled and interpreted languages
- Place each kind of fault at the stage that reveals it
Transcript
Everything said in the video, section by section (1,645 words). Read along, or search it.
Opening Problem
Text Cannot Run Directly
A processor doesn't read words. It executes numbered instructions, encoded as patterns of bits, each doing something tiny: copy this value, add these two, jump to that position. What you write is text: readable names, indentation, blank lines, notes to yourself. Nothing you type could ever be executed directly. Closing that distance is the job of a set of programs called the toolchain. Running them over your text is called building, and a successful build produces an executable. The build isn't one program doing one thing. It's a short assembly line, and each station has a narrow job, and a narrow view. That's the key. Every error message comes from one particular stage, and it can only complain about what that stage can see.
Overview
The Build Assembly Line
Here's the assembly line. Your source file goes into the preprocessor, which produces expanded text. The compiler turns that into an object file. And the linker joins object files with ready-made library code, to produce the executable. Each program reads one file and writes another. And a stop at any station means the later stations never ran. That alone tells you a lot, when something fails.
Stage One
The Preprocessor Substitutes Text
The first program to touch your file, the preprocessor, doesn't understand the language at all. It performs textual substitutions you've asked for. Pull in another file here. Replace this name with that text. Keep or discard this stretch, depending on a setting. Ask it to stop after that step, and count the lines. This file has 7. The preprocessed text has over 70,000, still readable, and nothing checked for sense.
Stage Two
The Strict One-File Compiler
The compiler does the real translation. It checks that what you wrote obeys the language's grammar, works out what each name refers to, and produces machine instructions. Two facts about it explain most beginner confusion. It's strict, so it won't guess past a malformed line. And it works on one source file at a time, knowing nothing whatever about your other files.
Object Files
Real Instructions With Unfilled Gaps
That second fact is why the compiler's output isn't a program. Compile with dash c, and you get an object file. It contains genuine machine instructions, plus two lists: names this file offers to others, and names it uses but couldn't find. Wherever a used name appears, the compiler leaves a gap, because it has no idea what address that thing will live at. So an object file is real work, correctly translated, and completely unrunnable. Try to run it, and the system refuses. The linker matches each unfilled name against a definition in the object files and libraries, writes in the real address, and marks where execution begins. Now it runs.
Trade-Off
Why Split Across Files
Splitting a program across files looks like extra machinery, until a program gets large. Then changing one file means recompiling just that file, and two people can work on two files at once. The price is the linker, and its own family of errors.
Comparison
What Each Station Can Object To
So here's what each station takes in, and what it's able to object to. The preprocessor takes your source text, and objects to an instruction it can't carry out, most often a file it can't find. The compiler takes the expanded text of one file, and objects to broken grammar, and to names misused, within that one file. The linker takes all the object files plus library code. It objects to a name nothing defines, or a name two files both define. And the run itself can only object to situations that exist once real values are present: a missing file, an impossible step, a value out of range.
Linker Demo
A Promised Function Never Defined
Here's the linker at work. This file promises a function called square, and uses it, but never defines it. Compile it alone: no complaint. The compiler trusts the promise, and leaves a gap. Link it, and the linker reports a name, not a line, because the fault isn't on any line. Nothing defines square.
Linker Fix
Supplying the Missing Definition
The fix is a definition the linker can find: here, a second file that defines square. Build both together, and every gap is filled. Seven squared is 49, just as the promise said.
Two Routes
Compiled Versus Interpreted Code
Everything so far describes the compiled route: translate everything first, ship the result, and run it later. There's a second route. An interpreter reads your source text and carries it out as it goes, a piece at a time, every time the program runs. So compiled code is translated once, and runs faster. Interpreted code is translated continuously, and runs slower. With compiling, anything the compiler can detect is found before the program runs. With interpreting, many mistakes stay hidden until execution reaches that exact line. Compiled code must be rebuilt for another kind of machine. Interpreted code usually just works, if an interpreter exists there. And for one small change, interpreting is immediate: change and run. Compiling means change, rebuild, then run.
Trade-Offs
A Range, Not Two Boxes
Neither one is the advanced choice. These are engineering trade-offs, not a ranking. Where speed and tight control matter, an operating system, a game engine, software inside a device, the compiled route wins. Where turnaround and portability matter more than raw performance, the interpreted route wins. And many widely used languages sit in between. They compile to a compact intermediate form, and a companion program runs it, translating the busiest parts to machine code as it goes. So treat compiled and interpreted as the two ends of a range, not two boxes.
Definitions
Four Kinds of Fault
The real reason to learn the assembly line is diagnosis. A fault is reported by whichever station first notices it, and that tells you what kind of mistake you made. A syntax fault is text that breaks the grammar. The compiler stops, names a file and a line, and produces nothing. A linking fault means every file translated fine, but a promised name is defined nowhere, or twice. The linker reports a name, not a line. A runtime fault is a valid program meeting a situation it has no valid response to. It builds, starts, and then stops. And a logic fault announces nothing. It builds, runs and finishes, and the output is wrong.
Demo: Syntax
One Missing Semicolon
Here are all four, for real. First, syntax: one missing semicolon. The compiler stops, and names the file, the line, and the column, and even suggests the fix. No program is produced. Add the semicolon, and rebuild. This time it builds, runs, and prints the change: 2.
Demo: Runtime
Character Six of Two
Next, runtime. This program asks for character six of a two-character code. It builds without a word. It starts, and then stops on its own, with an exception: out of range. The exit code says it didn't finish normally.
Quick Check
Change of 38 From Wrong Arithmetic
Now this one. It builds cleanly, runs, and finishes. Paid 20, price 18, and it says the change is 38. Quick check: which kind of fault is this, and why did nothing warn you? Pause, and decide. It's a logic fault: the program adds where it should subtract. Every stage was satisfied, because the code is perfectly valid. It just isn't what you meant. Only an expectation, decided before you ran it, catches this one.
Perspective
Loud Failures Are Good Days
Beginners dread the first kind, and that instinct is backward. A compiler fault is located for you, for free, in seconds. A logic fault ships, and gives confident wrong answers. A build that fails loudly is a good day.
Diagnosis Guide
How Far Did It Get?
So before you read the text of any error, ask one question: how far did it get? A file, a line and no program is syntax. Look at that line, and the line above it, because a missing terminator can be reported on the line after. Dozens of messages from one small change is also syntax. Read only the first one, fix it, and rebuild. The rest are usually the compiler's confusion. An undefined or duplicated name is linking: check the spelling, whether the file was in the build, and whether a library was supplied. A program that started, then stopped, is runtime: ask which input made this run different, and try the edges: empty, one item, zero, negative, the largest case. And if everything succeeds but the output is wrong, that's logic. Work the example by hand, and find the first point where the two accounts diverge.
The Workflow
The Tight Build-Run-Fix Loop
Nobody writes a whole program and builds it once. The work is a tight loop, and the size of each turn is the most useful habit you can adopt. Change one small thing. Build it, which checks syntax and linking. Run it on a real case, including awkward ones. And compare with what you expected. It's the arithmetic of suspicion. Change one thing, and something breaks: there's one suspect. Write two hundred lines and build for the first time, and the fault could be anywhere, with several mistakes hiding each other.
Good Habits
Making the Loop Work
A few habits make the loop work. Build far more often than feels necessary: building costs seconds. Decide what you expect before you run. Without an expectation, any output looks like an output. Keep the last working version, so a bad afternoon becomes twenty lost minutes. Run the awkward cases early. And change one thing between runs. This cycle is the work, not a sign of failure. Experience shows up as shorter loops, not fewer failures.
Key Takeaways
Summary of the Toolchain and Faults
To summarize. The preprocessor pastes and substitutes text, the compiler translates one file at a time, and the linker fills the gaps to make an executable. An object file has real instructions, but unresolved gaps, so it can't run on its own. Compiled code pays the translation cost once. Interpreted code pays a little on every run. Neither is the advanced choice. And faults come in four kinds, syntax, linking, runtime and logic, each found later than the last, at greater cost. Work in small loops, so every new fault has one suspect.
Think About It
The Total That Is Too Small
Here's something to think about. A program adds up a list of numbers, and reports a total that's always slightly too small. Which kind of fault is that? And why did nothing warn you?
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 The Build-Run-Fix Workflow
What stages turn C++ source text into a program I can run?
Why can't an object file run on its own?
What is the difference between compiled and interpreted languages?
How can I tell whether an error is a syntax, linking, runtime, or logic fault?
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 →