Search

1.11 — Debugging your program (stepping and breakpoints)

By Alex on November 16th, 2007 | last modified by Alex on March 29th, 2017

Syntax and semantic errors

Programming can be difficult, and there are a lot of ways to make mistakes. Errors generally fall into one of two categories: syntax errors, and semantic errors (logic errors).

A syntax error occurs when you write a statement that is not valid according to the grammar of the C++ language. This includes errors such as missing semicolons, undeclared variables, mismatched parentheses or braces, and unterminated strings. For example, the following program contains quite a few syntax errors:

1

2

3

4

5

6

7

#include <iostream>; // preprocessor statements can't have a semicolon on the end

Fortunately, the compiler will generally catch syntax errors and generate warnings or errors, so you easily identify and fix the problem. Then it’s just a matter of compiling again until you get rid of all the errors.

Once your program is compiling correctly, getting it to actually produce the result(s) you want can be tricky. A semantic error occurs when a statement is syntactically valid, but does not do what the programmer intended.

Sometimes these will cause your program to crash, such as in the case of a divide by zero:

1

2

3

4

5

6

7

8

9

#include <iostream>

intmain()

{

inta=10;

intb=0;

std::cout<<a<<" / "<<b<<" = "<<a/b;// division by 0 is undefined

return0;

}

Sometimes these will just produce the wrong value:

1

2

3

4

5

6

7

#include <iostream>

intmain()

{

std::cout<<"Hello, word!";// spelling error

return0;

}

or

1

2

3

4

5

6

7

8

9

10

11

12

#include <iostream>

intadd(intx,inty)

{

returnx-y;// function is supposed to add, but it doesn't

}

intmain()

{

std::cout<<add(5,3);// should produce 8, but produces 2

return0;

}

Unfortunately, the compiler will not be able to catch these types of problems, because the compiler only knows what you wrote, not what you intended.

In the above example, the errors are fairly easy to spot. But in most non-trivial programs, many semantic errors will not be easy to find by eyeballing the code.

Fortunately, that’s where a debugger can really come in handy.

The debugger

A debugger is a computer program that allows the programmer to control how a program executes and watch what happens as it runs. For example, the programmer can use a debugger to execute a program line by line, examining the value of variables along the way. By comparing the actual value of variables to what is expected, or watching the path of execution through the code, the debugger can help immensely in tracking down semantic errors.

Early debuggers, such as gdb, had command-line interfaces, where the programmer had to type arcane commands to make them work. Later debuggers (such as Borland’s turbo debugger) came with their own “graphical” front ends to make working with them easier. Almost all modern IDEs available these days have integrated debuggers -- that is, the debugger is built-in to the editor, so you can debug using the same environment that you use to write your code (rather than having to switch programs).

Nearly all modern debuggers contain the same standard set of basic features -- however, there is little consistency in terms of how the menus to access these features are arranged, and even less consistency in the keyboard shortcuts. Although our examples will be from Microsoft Visual Studio 2005 Express, you should have little trouble figuring out how to access each feature we discuss no matter which development environment you are using.

Stepping is a debugger feature that lets you execute (step through) your code line by line. This allows you to examine each line of code in isolation to determine whether it is behaving as intended.

There are actually 3 different stepping commands: step into, step over, and step out. We will cover each one in turn.

Step into

The step into command executes the next line of code. If this line is a function call, “step into” enters the function and returns control at the top of the function.

Let’s take a look at a very simple program:

1

2

3

4

5

6

7

8

9

10

11

12

#include <iostream>

voidprintValue(intnValue)

{

std::cout<<nValue;

}

intmain()

{

printValue(5);

return0;

}

As you know, when running a program, execution begins with a call to main(). Because we want to debug inside of main(), let’s begin by using the “Step into” command.

In Visual Studio 2005 Express, go to the debug menu and choose “Step Into”, or press F11.
If you are using a different IDE, find the “Step Into” command in the menus and select it.

When you do this, two things should happen. First, because our application is a console program, a console output window should open. It will be empty because we haven’t output anything yet. Second, you should see some kind of marker appear to the left of the opening brace of main. In Visual Studio 2005 Express, this marker is a yellow arrow. If you are using a different IDE, you should see something that serves the same purpose.

This arrow marker indicates that the line being pointed to will be executed next. In this case, the debugger is telling us that the next line that will be executed is the opening brace of main(). Choose “Step into” again to execute the opening brace, and the arrow will move to the next line.

This means the next line that will be executed is the call to printValue(). Choose “Step into” again. Because printValue() is a function call, we “Step into” the function, and the arrow should be at the top of the printValue() code.

Choose “Step into” to execute the opening brace of printValue().

At this point, the arrow should be pointing to std::cout << nValue;.

Choose “Step over” this time (this will execute this statement without stepping into the code for operator<<). Because the cout statement has now been executed, you should see that the value 5 appears in the output window.

Choose “Step into” again to execute the closing brace of printValue(). At this point, printValue() has finished executing and control is returned to main().

You will note that the arrow is again pointing to printValue()!

While you might think that the debugger intends to call printValue() again, in actuality the debugger is just letting you know that it is returning from the function call.

Choose “Step into” twice more. At this point, we have executed all the lines in our program, so we are done. Some debuggers will terminate the debugging session automatically at this point. Visual Studio does not, so if you’re using Visual Studio, choose “Stop Debugging” from the debug menu. This will terminate your debugging session.

Note that “Stop Debugging” can be used at any point in the debugging process to end the debugging session.

Step over

Like “Step into”, The Step over command executes the next line of code. If this line is a function call, “Step over” executes all the code in the function and returns control to you after the function has been executed.

Note for Code::Blocks users: In Code::Blocks, “Step over” is called “Next Line”.

Let’s take a look at an example of this using the same program as above:

1

2

3

4

5

6

7

8

9

10

11

12

#include <iostream>

voidprintValue(intnValue)

{

std::cout<<nValue;

}

intmain()

{

printValue(5);

return0;

}

“Step into” the program until the next statement to be executed is the call to printValue().

Instead of stepping into printValue(), choose “Step over” instead. The debugger will execute the function (which prints the value 5 in the output window) and then return control to you on the next line (return 0;).

Step over provides a convenient way to skip functions when you are sure they already work or do not need to be debugged.

Step out

Unlike the other two stepping commands, “Step out” does not just execute the next line of code. Instead, it executes all remaining code in the function you are currently in, and returns control to you when the function has finished executing.

Let’s take a look at an example of this using the same program as above:

1

2

3

4

5

6

7

8

9

10

11

12

#include <iostream>

voidprintValue(intnValue)

{

std::cout<<nValue;

}

intmain()

{

printValue(5);

return0;

}

“Step into” the program until you are inside printValue().

Then choose “Step out”. You will notice the value 5 appears in the output window, and the debugger returns control to you after the function has terminated.

Run to cursor

While stepping is useful for examining each individual line of your code in isolation, in a large program, it can take a long time to step through your code just to get to the point where you want to examine in more detail.

Fortunately, modern debuggers provide a few more tools to help us efficiently debug our programs.

The first useful command is commonly called Run to cursor. This command executes the program like normal until it gets to the line of code selected by your cursor. Then it returns control to you so you can debug starting at that point. Let’s try it using the same program we’ve been using:

1

2

3

4

5

6

7

8

9

10

11

12

#include <iostream>

voidprintValue(intnValue)

{

std::cout<<nValue;

}

intmain()

{

printValue(5);

return0;

}

Simply put your cursor on the std::cout << nValue; line inside of printValue(), then right click and choose “Run to cursor”.

You will notice the arrow indicating the line that will be executed next moves to the line you just selected. Your program executed up to this point and is now waiting for your further debugging commands.

Run

Once you’re in the middle of debugging a program, you can tell the debugger to run until it hits the end of the program (or the next breakpoint, which we’ll discuss in a second). In Visual Studio 2005 Express, this command is called “Continue”. In other debuggers, it may be called “Run” or “Go”.

If you have been following along with the examples, you should now be inside the printValue() function. Choose the run command, and your program will finish executing and then terminate.

Breakpoints

The last topic we are going to talk about in this section is breakpoints. A breakpoint is a special marker that tells the debugger to stop execution of the program at the breakpoint when running in debug mode.

To set a breakpoint in Visual Studio 2005 Express, go to the Debug menu and choose “Toggle Breakpoint” (you can also right click, choose Breakpoint -> Insert Breakpoint). You will see a new type of icon appear:

Go ahead and set a breakpoint on the line std::cout << nValue;.

Now, choose “Step into” to start a debugging session, and then “Continue” to have the debugger run your code, and let’s see the breakpoint in action. You will notice that instead of running all the way to the end of the program, the debugger stopped at the breakpoint!

Breakpoints are extremely useful if you want to examine a particular section of code. Simply set a breakpoint at the top of that section of code, tell the debugger to run, and the debugger will automatically stop every time it hits that breakpoint. Then you can use the stepping commands from there to watch your program run line by line.

One last note: Up until now, we’ve been using “step into” to start debugging sessions. However, it is possible to tell the debugger to just start running to the end of the program immediately. In Visual Studio 2005 Express, this is done by picking “Start debugging” from the Debug menu. Other debuggers will have similar commands. This, when used in conjunction with breakpoints, can reduce the number of commands you need to use to get to the spot you want to debug in more detail using the stepping commands.

Conclusion

Congratulations, you now know all of the major ways to make the debugger move through your code. However, this is only half of what makes debuggers useful. The next lesson will talk about how to examine the value of variables while we are debugging, as well as a couple of additional windows of information we can make use of to help debug our code.

I'm unable to assist you with this, as this appears to be a Code::Blocks specific configuration issue. Your best bet is to use Google search to see if you can find someone who has had the same problem.

Dear Teacher, please accept my many thanks for you replied and for your assistive answer. I did that with words "code blocks option 'nx'", and from resauts I chose "Images for code blocks option 'nx'". Then first image > click on image > http://wiki.codeblocks.org/index.php/MinGW_installation > 2.1 Installation > I followed instructions. Indeed in Debugger settings I configured "Default" (without quotes) and deleted gdb.exe I had added according to Stack Overflow suggestion. If you do not configure gdb.exe, default setting is Default. Eventually everything is okay. Regards.

When I tried to execute the step in command, I received the following error:
ERROR: You need to specify a debugger program in the debuggers's settings.
(For MinGW compilers, it's 'gdb.exe' (without the quotes))
(For MSVC compilers, it's 'cdb.exe' (without the quotes))

When I'm using step into, it will step through my program, but when it comes back out to main() and is running the "std::cout << "The sum of 3 and 4 is " << add(3, 4) << std::endl;" line, it will jump through all of these library files without outputting that code in the console window that opens up. For example, it will step through functions in "ostream", "iosfwd", "xiosbase", and a bunch of other files before it tries to read a file that is non-existent and errors out. None of this happens when I run my code normally.

Sir, what is the difference in function between "Run to Cursor" and "Breakpoint". They both seem to serve the same purpose of running up to a particular line of code after which we want to look carefully.

The two functions are similar. Breakpointing code will always cause the debugger to stop on that line (stopping there multiple times if relevant). Run to cursor causes the debugger to run until the current line is encountered. It's like using a temporary breakpoint on the currently line. Run to cursor is really a convenience command.

My dear c++ Teacher,
Please let me say I can not understand "Choose “Step over” this time (this will execute this statement without stepping into the code for operator <<)."
How is that statement "std::cout << nValue;" be executed without operator "<<" be executed?
With regards and friendship
Georges Theodosiou

My dear c++ Teacher,
Please let me a suggestion:
In "Step into" section after "Visual Studio does not, so if you’re using Visual Studio, choose “Stop Debugging” from the debug menu. This will terminate your debugging session."
add: "if you continue click "step into", another .cpp file will open and yellow arrow will indicate some line in it. You must close this file and click “Stop Debugging”".
Also in the "Run" section you say:
"If you have been following along with the examples, you should now be inside the printValue() function. Choose the run command, and your program will finish executing and then terminate."
But visual studio has not "run" command. "Continue" command (in Debug menu) and "Run To Cursor" in menu after right click with mouse pointer on a line do this job. Problem is that console window (the black one) disappears quickly and you can not see number 5.
With regards and friendship.

My dear c++ teacher,
Please let me send you my last comment for today.
1. In templates you have "PrintValue(int nValue)", capital first letter.
2. Between 2nd and 3rd templates and below 3rd you state "is the call to printValue()" and "the printValue() code", and "opening brace of printValue()". My understading is that you mean: function definition "void printValue(int nValue)", and that "printValue()" is function call.
Bonne journée.
With regards and friendship.

My dear c++ Teacher,
Please let me say you that in text between 2nd and 3rd template you state: "Because printValue() WAS a function call, we “Step into” the function ...". According to my bad english it means: "printValue() is NOT any more function call".
With regards and friendship.

My dear c++ Teacher,
Please let me express my gratitude for you replied my comment (my dear dsp Teacher Mr. Richard Lyons snobs me, he teaches me only by his book) and for suggested me a good document. It applies to version 5.11 but with some differences in names. For example instead of "next step" this version has "next line". Anyway it is helpful.
With regards and friendship.

My dear c++ Teacher,
Please let me say that as it is clear from the document you suggested me, debugging with Dev-C++ 5.11 is different than with Visual Studio.
Before clicking "Next line" (step into) I have to check (by clicking) breakpoint. When I click (set breakpoint) on line 1 (#include <iostream>) and then click "Debug", arrow (blue) appears on line 5 (std::cout << nValue;). When next I click "Next line", console window outputs "5", and arrow goes to line 6. When I click again "Next line" arrows goes to line 11 "return 0;" and after one more click on "Next line" it goes to line 12, end of program.
Now if I close file main.cpp and open it again, and set breakpoint on line 8 (int main()), and click "Debug", arrows goes to line 10 (printValue(5);). If then click on "Next line" console window outputs "5", and arrows goes to line 11, and after one more click on "Next line" it goes to line 12.
So, arrow never goes from function call: printValue(5) to function definition: void printValue(int nValue).
With regards and friendship.

I'm using Code Blocks 16.01 on Ubuntu 16.04 and I cannot get the 5 to print in the debugging window. By default Code Blocks launches xterm but stepping into and moving to next line does not display any value in the xterm console as shown:

http://imgur.com/dEf6cWK

Some forum posts on the Code Blocks forum and other places suggest changing some settings. For example, changing from xterm to gnome-terminal. However I have the exact same results:

http://imgur.com/pKQgQzK

I initially thought it was related to the message I see "warning: GDB: Failed to set controlling terminal: Operation not permitted", but multiple threads on the Code Blocks forums imply that this is a cosmetic issue and should have no effect on debugging functionality.

I have installed Code Blocks on a machine running Windows 10 and I am able to see the "5" value in the debugging window. This seems to be unique to either the the configuration of Ubuntu or of Code Blocks on this machine, however there is nothing I know of that has been modified.

My dear c++ Teacher,
Please let me say some problems I got using Code::Blocks 16.01.
1st: When first I choose "step into", yellow arrow appears not to the left of the opening brace of main(), but of the printValue(5);.
2nd: When for second time I choose "step into", yellow arrow appears not to the left of the opening brace of printValue(int nValue), but of the std::cout << nValue;.
Also let me following question:
You state: "Choose “Step over” this time (this will execute this statement without stepping into the code for operator <<). Because the cout statement has now been executed, you should see that the value 5 appears in the output window."
Yes, value 5 appears in the output window, but how "step over" executes this statement without stepping into the code for operator <<? My understanding is that this operator is including in this statement, then if operator is ignored, statement should not be executed.
With regards and friendship.

I wrote the article using Visual Studio 2015 -- some other debuggers might do things slightly differently. So your first and second point are fine.

Regarding your third point, step over does not ignore the statement -- it executes the statement without stepping into any functions, allowing you to skip past function calls you're not interested in debugging.

My dear c++ Teacher,
Please let me suspect that I have to follow your way: discover compiler's features by trial and error. Do you suggest me that?
I wish you happy new year and every year to come, and live many years for teach me c++!
With regards and friendship.

Alex:
Using Visual Studio 2015. Debugged printValue sketch and everything in tutorial went according
to plan up to the point of entering "Step out".After that a new screen with over 200 lines
of code popped up. My original screen was titled ConsoleApplication7.cpp . The new one was simply called
Miscellaneous. The cursor was at line 64 in this program. After fumbling around a bit I found that if I
repeatedly clicked "Step into" the cursor walked down the page and eventually ConsoleApplication7 came
back. The figure 5 did appear in the console output window after "Step out" was applied. After restoring
the ConsoleApplication7 screen with "Step into" clicks the output screen was blank. Is there an easy
answer?

Could have been something from the C++ standard library. Sometimes the debugger will pop into there and walk through all kinds of crazy obtuse code before returning back to your code. When that happens, an additional step out normally returns you to your code.

The function is named add(), so clearly the intent is to add the numbers, not subtract them. The add() function has a typo where the minus operator is being used instead of the plus operator, so the result of add(5,3) is 2 instead of the expected 8.