Chapter 15. Debug-On-Error Strategy

By this time you probably have your program written and containing a lot of sanity checks, some permanent and some temporary. Now it is time to test it. Let’s go bug hunting, one bug at a time. Our testing algorithm is very simple:

  1. Run your code with sanity checks on, trying to cover all possible cases.

  2. If any sanity check fails, fix the code and return to step 1.

  3. If you’ve made it to step 3, you can be reasonably sure your code works correctly. Well done!

In my personal experience, this strategy makes testing a much faster, more efficient, and more enjoyable procedure than it would otherwise be, when your code does strange things and does not provide any explanation for its behavior. All you have to do to make this process effective is to insert enough sanity checks in your code while writing it and to make them as informative as possible. In short, the more sanity checks you have in your code, the more you can guarantee that it works correctly after it has passed all the checks.

Let’s consider how the SCPP_TEST_ASSERT macro can be switched on. Take a closer look in the file scpp_assert.hpp, where it is defined:

#ifdef _DEBUG
#  define SCPP_TEST_ASSERT_ON
#endif

#ifdef SCPP_TEST_ASSERT_ON
#  define SCPP_TEST_ASSERT(condition,msg) SCPP_ASSERT(condition, msg)
#else
#  define SCPP_TEST_ASSERT(condition,msg) // do nothing
#endif

If you compile your project in debug mode, a symbol named _DEBUG is defined during compilation (this might be compiler-dependent, but it is definitely true for Microsoft Visual Studio). In this case, your sanity checks (e.g., the SCPP_TEST_ASSERT macro) are on. Our option for running the code are summarized in Table 15-1.

Table 15-1. Testing modes

LevelPurposeCompilation modeTest sanity checks
1Testing with debugging on errorDebugOn
2Fast testingReleaseOn
3ProductionReleaseOff

Options 1 and 3 are obvious enough: most of the time you will want to test your code while it is compiled in debug mode, and probably running it inside a debugger. However, if your program does a lot of number crunching, and if switching sanity checks on and compiling in the debug mode slow it down too much, you have option 2: testing the code compiled in release mode with sanity checks on. Not having the luxury of exploring the code in the debugger makes it especially important that your error messages contain enough information to allow you to fix the bug.

If your program is fast enough to run with sanity checks in debug mode, the easiest way to catch a bug is to open the scpp_assert.cpp file, find the comment “This is a good place to put your debug breakpoint:”, and put a debug breakpoint on the next line (which can be the line starting with either throw or cerr, depending on how the code was compiled):

void SCPP_AssertErrorHandler(const char* file_name,
               unsigned line_number,
               const char* message) {
  // This is a good place to put your debug breakpoint:
  // You can also add writing of the same info into a log file if appropriate.

#ifdef SCPP_THROW_EXCEPTION_ON_BUG
  throw scpp::ScppAssertFailedException(file_name, line_number, message);
#else
  cerr << message << " in file " << file_name
       << " #" << line_number << endl << flush;
  // Terminate application
  exit(1);
#endif

This is the reason I created this error handler function. Simply knowing the filename and line number where the error occurred might not help you much. But if you put your debugger breakpoint there, the debugger will stop on it during every execution of this line, even if the bug occurs on only the 10th or even the 10,000th iteration. By putting the breakpoint inside the error handler function, you are guaranteed that your program will run to the first error and stop in the debugger, as shown in Figure 15-1.

Debugger stopped inside the error handler function in XCode (Max OS X Leopard)

Figure 15-1. Debugger stopped inside the error handler function in XCode (Max OS X Leopard)

If the text of the error message is not enough to figure out why the error happened, you can go up the call stack into the function where the error occurred and examine the variables to figure out what happened and why. On the other hand, if your debugger doesn’t stop on this breakpoint, you should not be too disappointed—your program passed all sanity checks!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.37.191