3.6 — Using an integrated debugger: Stepping

When you run your program, execution begins at the top of the main function, and then proceeds sequentially statement by statement, until the program ends. At any point in time while your program is running, the program is keeping track of a lot of things: the value of the variables you’re using, which functions have been called (so that when those functions return, the program will know where to go back to), and the current point of execution within the program (so it knows which statement to execute next). All of this tracked information is called your program state (or just state, for short).

In previous lessons, we explored various ways to alter your code to help with debugging, including printing diagnostic information or using a logger. These are simple methods for examining the state of a program while it is running. Although these can be effective if used properly, they still have downsides: they require altering your code, which takes time and can introduce new bugs, and they clutter your code, making the existing code harder to understand.

Behind the techniques we’ve shown so far is an unstated assumption: that once we run the code, it will run to completion (only pausing to accept input) with no opportunity for us to intervene and inspect the results of the program at whatever point we want.

However, what if we were able to remove this assumption? Fortunately, we can. Most modern IDEs come with an integrated tool called a debugger that is designed to do exactly this.

The debugger

A debugger is a computer program that allows the programmer to control how a program executes and examine the program state while the program is running. 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 (logic) errors.

The power behind the debugger is twofold: the ability to precisely control execution of the program, and the ability to view (and modify, if desired) the program’s state.

Early debuggers, such as gdb, were separate programs that had command-line interfaces, where the programmer had to type arcane commands to make them work. Later debuggers (such as early versions of Borland’s turbo debugger) were still standalone, but came with their own “graphical” front ends to make working with them easier. Most modern IDEs available these days have an integrated debugger -- that is, a debugger uses the same interface as the code 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 use screenshots from Microsoft Visual Studio (and we’ll cover how to do everything in Code::Blocks as well), you should have little trouble figuring out how to access each feature we discuss no matter which development environment you are using, even one we’re not explicitly covering.

The remainder of this chapter will be spent learning how to use the debugger.


Don’t neglect learning to use a debugger. As your programs get more complicated, the amount of time you spend learning to use the integrated debugger effectively will pale in comparison to amount of time you save finding and fixing issues.


Before proceeding with this lesson (and subsequent lessons related to using a debugger), make sure your project is compiled using a debug build configuration (see 0.9 -- Configuring your compiler: Build configurations for more information).

If you’re compiling your project using a release configuration instead, the functionality of the debugger may not work correctly (e.g. when you try to step into your program, it will just run the program instead).

For Code::Blocks users

If you’re using Code::Blocks, your debugger may or may not be set up correctly. Let’s check.

First, go to Settings menu > Debugger…. Next, open the GDB/CDB debugger tree on the left, and choose Default. A dialog should open that looks something like this:

If you see a big red bar where the “Executable path” should be, then you need to locate your debugger. To do so, click the button to the right of the Executable path field. Next, find the “gdb32.exe” file on your system -- mine was in C:\Program Files (x86)\CodeBlocks\MinGW\bin\gdb32.exe. Then click OK.

For Code::Blocks users

There have been reports that the Code::Blocks integrated debugger (GDB) can have issues recognizing some file paths that contain spaces or non-English characters in them. If the debugger appears to be malfunctioning as you go through these lessons, that could be a reason why.


We’re going to start our exploration of the debugger by first examining some of the debugging tools that allow us to control the way a program executes.

Stepping is the name for a set of related debugger features that let us execute (step through) our code statement by statement.

There are a number of related stepping commands that we’ll cover in turn.

Step into

The step into command executes the next statement in the normal execution path of the program, and then pauses execution of the program so we can examine the program’s state using the debugger. If the statement being executed contains a function call, step into causes the program to jump to the top of the function being called, where it will pause.

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

Let’s debug this program using the step into command.

First, locate and then execute the step into debug command once.

For Visual Studio users

In Visual Studio, the step into command can be accessed via Debug menu > Step Into, or by pressing the F11 shortcut key.

For Code::Blocks users

In Code::Blocks, the step into command can be accessed via Debug menu > Step into, or by pressing the Shift-F7

For other compilers

If using a different IDE, you’ll likely find the step into command under a Debug or Run menu.

When your program isn’t running and you execute the first debug command, you may see quite a few things happen:

  • The program will recompile if needed.
  • The program will begin to run. Because our application is a console program, a console output window should open. It will be empty because we haven’t output anything yet.
  • Your IDE may open some diagnostic windows, which may have names such as “Diagnostic Tools”, “Call Stack”, and “Watch”. We’ll cover what some of these are later -- for now you can ignore them.

Because we did a step into, you should now see some kind of marker appear to the left of the opening brace of function main (line 9). In Visual Studio, this marker is a yellow arrow (Code::Blocks uses a yellow triangle). 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 to be executed is the opening brace of function main (line 9).

Choose step into (using the appropriate command for your IDE, listed above) to execute the opening brace, and the arrow will move to the next statement (line 10).

This means the next line that will be executed is the call to function printValue.

Choose step into again. Because this statement contains a function call to printValue, we step into the function, and the arrow will move to the top of the body of printValue (line 4).

Choose step into again to execute the opening brace of function printValue, which will advance the arrow to line 5.

Choose step into yet again, which will execute the statement std::cout << value and move the arrow to line 6.


Because operator<< is implemented as a function, your IDE may step into the implementation of operator<< instead.

If this happens, you’ll see your IDE open a new code file, and the arrow marker will move to the top of a function named operator<< (this is part of the standard library). Close the code file that just opened, then find and execute step out debug command (instructions are below under the “step out” section, if you need help).

Now because std::cout << value has executed, and we should now see the value 5 appear in the console window.

Choose step into again to execute the closing brace of function 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 three more times. 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, others may not. If your debugger does not, you may need to find a "Stop Debugging" command in your menus (in Visual Studio, this is under Debug > Stop Debugging).

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

Congratulations, you've now stepped through a program and watched every line execute!

Step over

Like step into, The step over command executes the next statement in the normal execution path of the program. However, whereas step into will enter function calls and execute them line by line, step over will execute an entire function without stopping and return control to you after the function has been executed.

For Visual Studio users

In Visual Studio, the step over command can be accessed via Debug menu > Step Over, or by pressing the F10 shortcut key.

For Code::Blocks users

In Code::Blocks, the step over command is called Next line instead, and can be accessed via Debug menu > Next line, or by pressing the F7 shortcut key.

Let's take a look at an example where we step over the function call to printValue:

First, use step into on your program until the execution marker is on line 10:

Now, choose step over. The debugger will execute the function (which prints the value 5 in the console output window) and then return control to you on the next statement (line 12).

The step over command provides a convenient way to skip functions when you are sure they already work or are not interested in debugging them right now.

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 currently being executed, and then returns control to you when the function has returned.

For Visual Studio users

In Visual Studio, the step out command can be accessed via Debug menu > Step Out, or by pressing the Shift-F11 shortcut combo.

For Code::Blocks users

In Code::Blocks, the step out command can be accessed via Debug menu > Step out, or by pressing the ctrl-F7 shortcut combo.

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

Step into the program until you are inside function printValue, with the execution marker on line 4.

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 (on line 10).

This command is most useful when you've accidentally stepped into a function that you don't want to debug.

A step too far

When stepping through a program, you can normally only step forward. It's very easy to accidentally step past (overstep) the place you wanted to examine.

If you step past your intended destination, the usual thing to do is stop debugging and restart debugging again, being a little more careful not to pass your target this time.

Step back

Some debuggers (such as Visual Studio Enterprise Edition and GDB 7.0) have introduced a stepping capability generally referred to as step back or reverse debugging. The goal of a step back is to rewind the last step, so you can return the program to a prior state. This can be useful if you overstep, or if you want to re-examine a statement that just executed.

Implementing step back requires a great deal of sophistication on the part of the debugger (because it has to keep track of a separate program state for each step). Because of the complexity, this capability isn't standardized yet, and varies by debugger. As of the time of writing (Jan 2019), neither Visual Studio Community edition nor the latest version of Code::Blocks support this capability. Hopefully at some point in the future, it will trickle down into these products and be available for wider use.

3.7 -- Using an integrated debugger: Running and breakpoints
3.5 -- More debugging tactics

174 comments to 3.6 — Using an integrated debugger: Stepping

  • Armando IG

    Hello, I can't find gdb32.exe, I have gdb.exe though, is it the same or should I download or look specifically for gdb32?

  • Bruh I can't use the shortcut for step into after running the program because f11 makes the console application fullscreen.

  • Graeme

    I can't use the "step into" function in VS 2019. It showed a screen that said something along the lines of "~~~.pdb missing". I don't remember the exact file so I can't really go looking for it. I attempted to load it without selecting a source and it didn't find anything. Now whenever I click Step Into, it just shows me a screen saying "Source Not Available; Source information is missing from the debug information for this module". I can't seem to get the first screen to show back up and let me try properly searching for the file. I've looked around stackoverflow and the answers there didn't help at all. I've looked through the options screen, tried loading all symbol files, looking through the project properties, seemingly everything a beginner could hope to do.

    • Graeme

      Okay, so after some messing around, playing with even more settings, and just generally playing with Visual Studio, I found that the only instance in which I can't use "step into" is if I: start the program in debugging, wait for it to come to an input, click the "break all" button (looks like a pause button), then try and step. Otherwise it works perfectly at cursor stops, breakpoints, or just by simply pressing f11 before it's running. I don't know if this is "intended behavior" of VS, but it seems to work well enough for me.

  • Sue


    If I step over a function that calls another function, is the debugger going to execute both functions at once?

  • sk

    After clicking on step in it just gives debugging finished with status 0 without the arrows or anything, why?
    Also appreciate this website and the work you've done,thank you!

    • Jeffrey Meyer

      I have the same problem - using Code::Blocks.  When I use "Step into" it rebuilds with the following last three lines of the DeBugger logs:

      Debugger name and version: GNU gdb (GDB) 8.1
      Starting the debuggee failed: No symbol table loaded.  Use the "file" command.
      Debugger finished with status 0

    • Jeffrey Meyer

      Sorry Guys, I feel like an idiot!
      I had Code::Blocks running in "Release" mode instead of "Debug".
      Now everything's working just fine, and I second sk's comment about the work done on this web site.

  • Shareware

    Hi Alex, I'm scratching my head about how you stepped into code that doesn't have any breakpoints? Your next lesson is about breakpoints, so it seems it's possible to enter debug mode without breakpoints? If I run debugger, I just get the printed value and it says Debugging Finished. So it executes the program at blistering speed and then finishes. Any clues on how you got things to work?

  • Daniel

    i never get the console output window , i just see a black screen flashing, then it goes back to the code.Should i change something in my settings?Because eveerything works fine when im running the program,its only when im trying to debug it that i never get the output window

  • Karl Phazer

    Weird debugger behavior.

    Hi, I was just trying out stuff and came across with an odd phenomenon. I'm using Visual Studio 2019 and I have this very simple code which works perfectly OK if I build it with release configuration, but causes an "Assertion Failure" if built & run with debug configuration:

    Even in debug mode the program executes seemingly right but eventually an error window pops up, saying:

    "Debug Assertion Failed!

    Program: <path>/<solution name>.exe
    File: minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp
    Line: 908
    Expression: is_block_type_valid(header->_block_use)""

    Is the code in some way inherently wrong, or is this just some sort of Visual Studio debugger quirk?

    • nascardriver

      You're dynamically allocating a `Container`, which you then _copy_ into `b`. `b` has automatic storage duration. The dynamically allocated `Container` is already leaked at this point, you don't have its address anymore.
      You cannot `delete` variables with automatic storage duration (`b`).

      If you make `b` a reference, your code will work because `b` is a reference to a dynamically allocated `Container`, which can be `delete`d.

      • Karl Phazer

        Well, shoot!

        This is so obvious now, but shows how hard as simple thing as pointers can be. I seem to drop all my logic in some cases with them.

        Your answer cleared a lot, thanks man!

      • Karl Phazer

        Once again I feel humbled by your efforts.

        The text content (which is kept updated) alone is a huge service to people wanting to learn C++. The fact that you tutor us by answering our (many times incoherent and badly formulated) questions is beyond awesome. I bet you get a ton of them each day.

        I hope you get something out of advertising and promise to support you with a donation as soon as I can afford to do so!

        I have also whitelisted you on my adblocker and strongly suggest everybody else doing so too.

  • Nico Gentile

    First of all THANK YOU (I really appreciate) the excellent work done with this site, thank you!

    Regarding the lesson, concisely the "jump" instruction ("Set next statement" in Code Blocks), I tried to throw an error skipping the line where the variable "x" is instantiated ...
    The thing is, if I comment that line it results in a compiler error (as it was supposed to), but if I skip that line with the debugger there is no such error

  • Oskar

    Hi, had a bit of trouble enabling the debugger on Linux so I'm going to post how I did it here so that other Linux users don't have to struggle.

    1. Make sure you have GDB installed (I recommend looking into /bin/ folder)
    2. After you installed GDB you can find the programs/script in /bin/.

    Hope this helps anyone

  • Mohammad

    I am using code::blocks the latest version on win 10.
    When I use the “step into” from debug menu, it works fine except that the debug arrow does not show when execution goes into a function.
    Has anyone encountered the same issue?
    How can I see the debug arrow within a function which is defined outside of the main (but still inside the same file as main)?

  • 3LI M 3alim

    I face a problem, whenever I try to use a 'step out' command, something goes wrong.
    a small window pops-up saying
    "gdboring.exe has stopped working
    A problem caused the program to stop working correctly.
    Windows will close the program and notify you if a solution is available"

  • sami



    I've noticed that using "step into" debugging feature, we get to examine standard library codes for operator << in std::cout. As you said on Library part, Standard Library are binary machine language and for security reason the businesses won't want to publish their source codes. Then how come we are able to access them through debugging tools?

    2) My code contained std::cin, and I used "step into" feature, but unlike std::cout, the debugger won't go into cin, why? isn't the ">>" operator a function like "<<" operator?

  • Zezima

    "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". This didn't happen for VS 2019. It went right over to return 0;

    • ryan fritz

      the same thing happened in code::blocks the Yellow Arrow(in code::blocks) started in function call, returned at "return 0;" i think it's just a functionality difference.

  • Chayim

    In subject "Step into":
    Under the third box; -When you program-
       Should be "When your program"

    A few words later; -execute the your-
       Should be "execute your"

  • HolzstockG

    So as I understand using approaches to find the issue inside of code from last 2 lessons except logger are useless because of use of debugger yes?

    • nascardriver

      Loggers aren't useless. You can't always debug your programs with a debugger (easily) (It's a remote process, it's running in a process that doesn't allow debuggers to be attached, it's not a debug build, ...), so you'll have to fall back to other methods.

  • Deepak Budha

    Hi, next line and step out options are disabled in Debug menu in Code::blocks. Could you please tell me why is it so.

  • adamamiga

    When you first say "Choose step into to execute the opening brace, and the arrow will move to the next statement (line 10).", it's not clear how to do that. Perhaps add "Hit F11 to execute the next line and continue to use F11 to execute the code line by line."

  • Anastasia

    Is lldb the best choice as a c++ command line debugger? Or should I stick with gdb (it seems to be more complete) ?
    And is it important to debug executables compiled with clang with lldb and those compiled with gcc with gdb or I can mix things up?

    Sorry for lots of newbie questions, but I'm a bit lost as to which debugger I should be getting used to, they seem to be using different sets of commands.

    • > is it important to debug executables compiled with clang with lldb and those compiled with gcc with gdb or I can mix things up?
      It doesn't matter, use whatever you like. According to the lldb homepage, "lldb leverages the clang compiler infrastructure". It's likely that lldb works better with clang than gdb does. I haven't use lldb, but I also never had problems with gdb. Looking at the command map ( ), they seems to be mostly the same, with gdb being easier in some situations.
      I haven't been disappointed by llvm's products so far, give it a try if you want to. Switching back to gdb should be easy if things don't work out.

      • Anastasia

        Yep, the commands are similar, but it seems gdb's commands can be used slightly differently (they are not so strictly structured as in lldb (lldb's tuto says)). And yes, they seem to be easier too...
        For example to find source line info:
        - (gdb) info line 0x1ec4
        - (lldb) image lookup -v --address 0x1ec4

        What I like more about gdb is that it also seems to be better documented. I mean, just look at the index:

        I'm afraid to not being able to find as much information about lldb and I surely will need it, because I have absolutely zero experience with debuggers :/

        Probably I will use gdb then if you are using it and never had any problems with it. Thanks!

  • luigi2406

    "when you execute the your first debug command"
    ^just a little error

  • Friendly Stranger

    Alex your cat is so cute :P

  • Jose

    Hi, I´m using VS 2019, this may be a stupid question but is there a way to see the printed lines aside from the console window?

    In order to go step by step, VS window has to be the active one but this way I can´t see my console window because it gets behind VS, the only way is not having VS maximized or having two monitors.

  • Eric

    I keep getting there were build errors and can't step into my code. I'm on Visual Studio 2019 Community
    EDIT: Nevermind, I realized my printValue function was an int instead of a void

  • Horst H. von Brand

    cout is usually line buffered, until a line is complete, nothing is printed.

  • petr

    If you want to be sure the number is printed, you have to flush the output buffer, \n might not be enough. Use


  • Mario

    I stayed up until 7 am trying to find out why my console wasn't printing the value 5 after it passed the print statement. After trying a bunch of things I restarted my code and trying to do the same with the default hello world file that exists when a new project is created in CodeBlocks. To my surprise... it worked file! The difference was in the new line character. For some reason without endl or \n (both work to combat this issue) nothing is printed. Beware!

Leave a Comment

Put all code inside code tags: [code]your code here[/code]