Nancy Cluts
Developer Technology Engineer
Microsoft Corporation
July 17, 1998
The following article was originally published in Site Builder Magazine (now known as MSDN Online Voices).
It's a fact of life. Nobody's perfect. Which is why no script or code written by a human can be perfect, either (although there are some very clever developers who get frighteningly close). There's always a different way to accomplish the same task, and, if you are trying to get something done in a hurry, you are likely to make mistakes. In computer parlance, these mistakes are called bugs, and getting rid of them is not called extermination, it's called debugging.
If you already know how to read a trap screen, or can trace an instruction using SYMDEB, you are probably a seasoned developer, and this article is not for you. Go back to your machine and see if that compile is finished. But if you are new to the language of programming, this article will help you understand what debugging is, why you must do it, and how you can go about ridding your script or code of those nasty bugs.
Debugging is a method used by software and content developers to figure out where the problems are in their code or script.
A popular, quite possibly apocryphal, anecdote about the origin of the term "bug" dates to the early days of computing. A program that was running developed a problem. The programmer (whose identity is hotly debated in various Internet newsgroups) went back to the code to diagnose the problem. The code looked clean, so the machine itself was checked and, lo and behold, the real problem was an insect in the hardware. Thus, the first "debugging" occurred.
Nowadays, you are unlikely to find actual insects in your machine, but you are likely to find such common bugs as:
Even if you have done a diligent job of finding and fixing bugs, users are bound to find obscure problems. This doesn't mean that you should forget about debugging. It's still important. If you create a site that contains many script errors, people won't visit it. If you create a control with errors, the control won't be used. The trick is to employ due diligence in debugging your script or code before you post it to the masses.
I've polled the developers in my group for their favorite methods of debugging. This section will give you a list of common problems with some common solutions and should get you on the right track when debugging your script or code.
I know that this sounds obvious, but there are some things that you can do that will help you avoid common problems. This section goes over some of the most common places you'll run into bugs.
If you are using Microsoft Visual Basic®, be sure to Dim all variables. Visual Basic allows the developer to use variables that haven't been explicitly declared. But it is a good programming practice to avoid taking advantage of this and declare all variables (via Dim) before using them. This will save you the headache of discovering later that the variable that you thought you were using wasn't the one you initialized (i.e., you initialized a variable named addresses and later on referred to it as address instead).
If you are using Active Server Pages (ASP) technology, turn on the Option Explicit option in your .asp file. This is related to the previous suggestion. Turning on this option helps to identify undefined variables -- you will get an error message for undefined variables in your .asp file.
There are several different ways to track variables in your script. In the old days of the computer industry, we used the printf() function to write the values of variables to screen that we thought were corrupt (getting trashed, in techy terms). The method that is akin to this, using JScript, is the function:
window.alert(someVariableOrProperty);
You can also send messages to the status bar using:
window.status = someVariableOrProperty;
Another method of checking a number of variables is to put a text-area on the HTML page and write values to that. Think of it as a simple HTML-debug window.
document.forms[0].myTextarea.value += someVariableOrProperty + "\r\n";
You can use a pseudo-debug mode that can be turned on and off by declaring a global variable. For example, you can create a variable called bDebugMode and make a series of window.alert() statements dependent on whether this variable is true or false. For example:
if(bDebugMode) window.alert(someVariableOrProperty);
Finally, there is the window.onerror() event used in Internet Explorer 4.0. This function allows the cancellation of the default event (by setting "true" as the return value) and defining alternate error handling. An example of this method is:
function handleError() { var sErrMsg = "Hey, there's an error! \n" + arguments[1] + "\nLine " + arguments[2] + "\n" + arguments[0]; window.alert(sErrMsg); return true; } window.onerror = handleError;
If you use both JScript and Visual Basic Scripting Edition (VBScript), you are likely to run into some common syntactical inconsistencies. For a developer new to JScript (especially after experience with VBScript or HTML), case-sensitivity of the language (and of the objects referred to by the language), can be an issue. In VBScript, you can write: Window.Open or window.open. In JScript, you have to use window.open(). Some other little things to look for are:
Be careful to release interface pointers. Don't rely on the container to clean up your mess. Use smart pointers or the CComPtr classes in the Active Template Library (ATL) to avoid this, and watch for paths of execution that may circumvent your interface pointer cleanup (such as exception handlers and if (FAILED(hr)) return;).
Stress test to find resource leaks. Running ASP components and ISAPI DLLs through WebCat helps to spot resource leaks (including unreleased interface pointers).
(Was that you I just heard saying "huh?" What's a "DLL?" What's "WebCat?"
Okay, bonus Geek Speak. Here goes:
A Dynamic Link Library (DLL) is code that contains functions you can call from other executable code (either an application or another DLL). The big difference between a DLL and an executable (EXE file) is that the DLL cannot be directly run. With an EXE, you can double-click the file's icon, and the code associated with the icon will run. DLLs must be called from other code that is already executing. Programmers use DLLs in order to provide code that they can reuse and to parcel out distinct jobs. The Windows operating system is itself a small executable that calls into several DLLs to handle the functioning of the system. For example, the file commdlg.dll contains the code that the system uses to implement the common dialogs (File Open, Print, and so on).
The Web Capacity Analysis Tool (WebCat) runs simulated workloads on client-server configurations. Using WebCat, you can test how Internet Information Server (IIS) and your network configuration respond to a variety of client requests. The results of these tests can be used to determine the best server and network configuration.)
Don't create threads needlessly. Used to excess, they can waste a lot of time performing context switches. Use worker thread pools to service request queues, as opposed to creating a thread for every user (this scales horribly). If you are going to use multiple threads, be careful to remember that you must provide synchronization , don't hog the processor , and watch out for deadlocks .
Setting the registry key ThreadingModel = Free does not make your component free-threaded; it tells the system that you have created a component that can be safely used in multi-thread environments. You still have to do the work to make sure that this is, in fact, true.
This does not mean that you have to go out and buy lots of machines for lots of different configurations. If you can afford an extensive testing lab, that's great -- but what do you do if you are a small shop? Use your friends. Ask your friends and co-workers to test out your script on their browsers and platforms to find inconsistencies. This helps you cover more bases than you could normally afford.
If your friends happen to be developers, you can also ask them to take a look at your code. When you create script or code, you understandably assume that what you have written is correct. Sometimes, it's hard to see some glaring omission or error in logic. This is where a set of "fresh eyes" comes in handy.
In code, many developers fall back on the compiler to do the syntax-checking for them. This is lazy, but busy people sometimes rely on tools rather than their own brains. This works well for finding typos and glaring errors and, to be fair, the compilers on the market today are very good at finding syntax errors or ambiguities. In the world of script, it is easy to be lulled into a sense of complacency by relying upon the browser to find all of your scripting errors. This is folly -- the browser can't find logical errors.
Not that you shouldn't use the tools that are available. I would encourage you to use every tool you can find that will root out potential problems (i.e., the Script Debugger with Internet Explorer 4.0 and WebCat for performance testing). If you are creating a control, set the warning level as high as possible and you will see all sorts of places where you might have written some sloppy code. Cleaning it up early in the development phase not only helps you to learn good programming practices, but it saves problems later, when you go back and have to change some common method you had improperly used over and over again in your code.
In short, don't forget to think about the 0, negative, and n+1 cases in your script or code. Your math teacher drilled this into you, but it may have been a very long time since you took that math class. Basically, this means that you need to think about what happens in the zero case What if cookies are turned off? What happens in the negative case? Can your loop go negative and put you into an infinite loop?. What happens in the n+1 case? Have you accurately given the end point in a loop?
Contrary to popular belief, testers were not put on this earth to find all of the logical and syntactical errors of the programmer. Testing is an art in and of itself. I wrote an article, Getting Testy? Your Users Will Thank You, that covers testing in general; you may find it useful.
One type of testing that doesn't require a degree is called "monkey testing." This form of testing is akin to just pressing all of the keys at once or choosing strange key combinations and seeing what happens.
Debugging is a necessary and sometimes arduous task. The more you debug, the better you will become at it. You will also learn what scripting errors you most commonly make, and will reactively avoid them in the development phase. The list of pitfalls I have given you is not comprehensive. They are merely the most common ones many developers run into from time to time when creating a Web site. Don't worry if your script isn't perfect; nobody's perfffect.
Be real nice to Nancy Cluts, MSDN Online's developer-technology writer extraordinaire, and maybe she'll take you for a ride in that gorgeous red convertible.