How To Use A Debugger

This is part of a larger series known as “How To Program Anything: Core Rulebook

Preface

Note: This article discusses the average visual debugger (a debugger with a graphical user interface) for an imperative language, such as C, Java, JavaScript, Python, PHP, etc.  If you’re not sure what imperative means but the language you are using in the style of one of these listed languages, you are in the right place.

While you are programming you have to keep in mind how all the parts of whatever section you’re working on work together.  You are constructing a program-flow and data-flow in the abstract, being in your mind, as you tell the computer what to do.  When you run the program, the computer executes all your carefully crafted instructions one by one at a blazing fast speed and you get your results, whether it’s a command-line tool outputting textual information, or a graphical user interface with lots of buttons, or a game world complete with 3D models.  And then, an error happens; something doesn’t work right, or the program crashes due to a segmentation fault, or a character in a game is completely unresponsive.  What do you do then?  Unfortunately, you can’t seem to slow the computer down, see what it is “doing” as it executes each step of your program so you can track down exactly where everything is going wrong… or can you?

Debugger’s are extremely useful tools in programming precisely because, in the general arena, they do exactly that.  Fortunately, debugger’s, like integrated development environments (see “What is an IDE?“), have come a long way in usability.  It used to be that you would run a debugger, such as GDB from the command line, and give it commands in a textual format as it worked through your program.  I had to do that when I worked as a print-job programmer for a financial statement printing plant, and it was not fun.  In fact, it was confusing and extremely clunky.

In this article I hope to show you the basics of using a GUI debugger that can be applied to all GUI debugging environments (at least for imperative programs).  As the note above says, if you are programming in a general purpose (imperative) programming language such as C, Java, JavaScript, Python, PHP and such, this article should apply to you with little changes.  I’m going to cover the basics of “stepping” through code, and then move on to what are known as breakpoints.  Along the way we’ll be examining call stacksscoping and variables.  Finally, we’ll move on to watch expressions, which not all debuggers have but can prove to be a useful feature to know.

To provide us with a working example, we’ll be using the built-in debugger that ships with the Firefox web browser.  We’ll be performing these basic debugger actions and displaying these concepts in the execution of a simple JavaScript program.  Debuggers for all major browsers exist, including Chrome and Safari, and originally I was going to use Safari as my example.  However, I discovered that a major number of Safari versions still don’t implement watch expressions, and this was a topic I wanted to cover.  So, Firefox it is then!  I’ve opted to employ a two function selection sorting algorithm as my example.  We will be using the Firefox JavaScript console in this example which is specific to JavaScript, but outputting textual data to StdOut or StdErr is usually pretty straightforward in many other languages such as C or Python.  For “printing” to these streams you’ll have to consult your language’s reference.

Setting Ourselves Up

This tutorial actually has some baggage to download if you want to try it out at home, unlike some of my previous tutorials about the nature of things and what things are.  Fortunately, it’s not much, simply consisting of one file with some extremely bare-bones HTML inside it, and the JavaScript we’re going to debug.  To play along at home, simply download this html file and open the file (debuggerexample.html) in your Firefox web browser installation.  Then in your menu, click “developer” and then “toggle tools.”  From here click on the “debugger” tab.  You should see something like this:

Click To See A Larger Version

Examining The Code

Our accompanying HTML file is made up of a few elements.  The base HTML that makes up the page (that is, the welcome text, the empty input text field, the empty output text, and the compute button) looks like this:

The JavaScript, which holds all the code for our program reads like this:

The purpose of this code is to sort a series of numbers entered into the input HTML element (separated by spaces) from “smallest” (least), to “largest” (most), and output that list of values (separated by spaces) into the output HTML element.  This code consists of three functions (if you are unfamiliar with functions and variables please consult my article Programming Crash Course Part 1).  The first function is a companion to the second function, and searches for the minimum value in a list starting at a particular index and returns its index.  The second function is our sorting algorithm, and takes the following steps:

  1. Set the current index to the beginning of the list: i = 0
  2. Start at the current index and find the smallest value in the list
  3. Swap the value at the current index with the smallest value in the list
  4. Increment the current index and repeat from step 2 until we are at the end of the list

The third function takes this functionality and “maps” or plugs it into the HTML form elements we’ve constructed.  This function is run/called every time somebody clicks the “compute” button on the web page.

Setting A Breakpoint

So, how do we examine this code with a debugger?  Well, the first thing we need to do is indicate to the debugger where we would like to stop or pause code execution.  For example, if we wish to examine the entirety of this code from the get go, a good place to stop would be right at the beginning of the compute() function.  This is where the concept of breakpoints comes in handy.

Essentially a basic breakpoint is a spot in the code indicated by the programmer where execution of the program is to be paused and control handed over to the debugger.  We’re going to “insert” a breakpoint right at the beginning of the compute function, that being on line 31.  Now, to indicate a breakpoint in the Firefox debugger we simply click on the line number to the left of the code to indicate where we’d like to pause.  So try clicking on line 31 (the actual line number) and you should see something like this:

This tells the browser in this case that as soon as someone clicks on the button and compute() gets executed, before we start we’ll pause and hand control over to the debugger.  Now if I click on the compute button my screen should change slightly to indicate I’m in the debugger and have gained minute control over my program.  In this case, the “code stepping” buttons should be live.

Stepping Through Code

The lower part of your screen should look something like this:

Here’s the meat and potatoes of the debugger. We are now paused inside the code.  To the right we can see the values of the variables that are going to be defined and filled out.  In the code the line we are paused at is highlighted.  The program has just entered the first function and is ready to start assigning variables.  What’s most important at the moment are what I call the “stepper” controls in the upper left.  I’m talking about these:

These are the buttons that are going to allow you to control how your program executes as you examine its mechanics.  From left to right we have “step over”, “step into”, and “step out of”.  Each type of step does something specifically different.  From the top:

  • “Step Into” – If you are on a line where a function gets called, this particular tool will actually “follow” your code “into” that function.  Control will be transferred to the beginning of that function, much like it was at the beginning of compute() with our breakpoint.  So, if we are on the line that contains the call to selectionSort(), clicking this stepper will move us to the beginning of selectionSort().  If we are not on a line with a function call, then this simply steps to the next instruction in the program.
  • “Step Out Of” – If you are currently inside a function this stepper will execute the rest of the function (barring it runs into any other breakpoint or error), and then return you to the line where you stepped “into” the function (being the line where that function was previously called.)  This is useful if are done checking the instructions of a function and need to move on to the rest of the program.
  • “Step Over” – This executes all the instructions on a given line without going “into” the called functions.  It’s basically a move to the next line button.  If there are function calls on a line, they are executed, and the very next line of where the program control is currently will receive the focus.  This is useful if you know your function being called works and want to move on to other parts of the program. You don’t have to step through the whole function being called.

You can only work with the steppers if the program is already paused.  That’s why we had to set a breakpoint before we could access the steppers.

Variables

This brings us to another important feature of debuggers.  They often display the values of the various variables in the various scopes that are pertinent to the moment the program is paused.  In fact, now that we are at the beginning of the compute() function, try stepping over the instructions in the compute() function and watch on the right as the variables in this function scope are defined and assigned to their identifiers.  You should end up with something like this on the right hand side of the debugger window:

Being a JavaScript debugger there are multiple scopes containing their own variables, but we are interested in the variables present in our compute() function.  As you can see as we assign them step by step in the function, their representation gets filled out in our variable inspector.  This is a super handy tool because you can see in real time how an variable is affected and what values it currently has, rather than having to keep track of it in your mind.

Alright, let’s his the play button (to the left of the stepper controls) and get the code to fully execute.  Now, to remove the breakpoint at line 31, simply click on it again.  This time we’re going to set a breakpoint further “into” the program (meaning two function calls into its operation).  So set a breakpoint on line 7 inside the findLeastRemaining() function.  Now, click the Compute! button once more.

Call Stack

In structured programming that uses functions its common that a function will call another function, which will call another function, and so on and so on.  This forms a sort of breadcrumb trail through the program, which the program execution follows back and forth as it executes and returns from the functions being called.  This breadcrumb trail can be represented by the call stack.  It is called the call stack because as each function is called, it places the current function information on a stack, literally stacking itself on top of older function references in memory.  So, if I call compute(), it’ll call selectionSort() which in turn calls findLeastRemaining(), and each one of these calls registers an entry in the stack.  We can actually see this stack in our debugger.  Right now, you should be paused on line 7 in the findLeastRemaining() function.  To your left there is a column with two tabs, the right being, you guessed it, “Call Stack.”  Click on that now, and the lower left hand of your screen should look something like this:

This is an incredibly useful tool.  You can set a breakpoint in a function, and then find out when and where it’s called from anywhere in the code.  This enables you to see how your program got to the point it got to, and in this particular debugger, if you click one of the entries it’ll actually highlight the line in the code where that function call was made.  Nifty!

Conditional Breakpoint

Sometimes a program is so repetitious that you don’t want to be caught in loop after loop looking for a particular condition to occur.  You know what condition is occurring that isn’t right, and you want to hone in on that particular situation.  There’s hope!  Not all debuggers have this, but many do.  In Firefox you can set a conditional breakpoint.  This is a breakpoint that depends on an if-clause like expression that evaluates to true or false.  If you right-click on a breakpoint while you’re in the current scope in Firefox you can add a condition to that breakpoint.  This changes the breakpoint color from blue to orange.  Let’s try it out.  First click on your line 7 breakpoint to clear it, and then click the run button to the left of the stepper controls.  You should have a clean plate.  Now click on 22 and set a breakpoint.  Right click on this breakpoint and convert it to a conditional breakpoint.  My Firefox was finicky of when I could actually accomplish this so you may have to fiddle with it.

Now in this part of the code list[i] is going to equal one of the numbers being sorted at any given time.  Let’s make our if-clause of our conditional breakpoint  list[i] == 4 Now, run the program again by clicking compute().

You should see something like the following in the lower part of your screen:

As you can see, we are paused right on line 22.  If we look to our right and examine our variables, you’ll see that i is equal to 2, and the second entry in list is equal to four currently.  This is right in line with our condition.  In fact, list[i] won’t equal four again after this, so hit run and you’ll see that’s the only time that breakpoint is considered by the debugger.  As noted, this is powerful tool when you want to check for or pay attention to a particular situation in programming without slugging through lots of circumstances where everything works fine.

Watch Expresssions

This leads us to watch expressions.  These are basically expressions, usually simply variable identifiers, that flash or show some specific effect when they are changed.  Say I’m in a function with a variable text1 that has a lot of properties.  Throughout the function many different function calls may effect the properties of this object in various ways.  I want to know when a particular variable’s properties are changed in executed code, the expression I’m tracking can tell me easily and quickly without having to slug through large hierarchies of objects.

You can add a watch expression in the Firefox debugger by simply selecting a variables and right-clicking to select “make a watch expression from selection”.  Or, you can enter an expression right under “add watch expression” in the variables pane.  This is a hit and miss feature of most compilers, and many compilers have this feature, but many don’t.

Try experimenting around with watch expressions, entering in different expressions, such as minimumIndex and see what values it takes on for itself as you step through the code.  This’ll give you an idea if you try various number of variables on how the feature works.

Conclusion

Debugging programs is hard work.  It can require the utmost attention to every little detail, and particularly with debuging code you didn’t write yourself, hours of slogging through the the specific ordered instructions of a program to see how it works.  However, that in itself is invaluable, and I often run a piece of software through a debugger to see how it works when I’m unfamiliar with the code.

In the “olden days” of the internet there were no good JavaScript debuggers built into web browsers, and developers had to debug their programs “by hand” and trial and error.  I have not covered an exhaustive number of debugging methods, as there are many that don’t necessarily involve a debugger, but I’ve seen whole written on the subject and that is out of the scope of this article.

Many debuggers of this nature are similar, and in this I hope that what I’ve outline here will be useful to you in the future.  Thanks for reading!

This is part of a larger series known as “How To Program Anything: Core Rulebook

If you appreciate this article you might consider supporting my Patreon.

But if a monthly commitment is a bit much, I get it, you might consider buying me a coffee.

photo credit: sparr0 ICE-286 big board, pan 3 via photopin (license)

kadar

I'm just a wunk, trying to enjoy life. I am a cofounder of http//originalpursuitssoc.com/ and I like computers, code, creativity, and friends.

You may also like...

Leave a Reply

%d bloggers like this: