[Home]
[Contents]
[Prev]
[Next]
8. Testing an Application
This chapter provides an overview of building, running, and
debugging an application in Digital Mars C++. Whenever you finish
making any significant addition or change to the source files of an
application, it is wise to test the result and verify that you have
achieved your goals. To do so, you must first build (or rebuild) the
executable so that it incorporates your modifications. Then you must
observe its behavior— either by tracing through modified sections, or
at least by running the application under the control of the
debugger.
This entire phase of the development cycle can be carried out in the
IDDE. Because all debugging in Digital Mars C++ takes place within
the IDDE, you do not have to leave the IDDE and run a separate
debugger. The IDDE itself provides a wealth of tools for examining
all facets of your application's structure and behavior.
Two other chapters present detailed information about the
debugging capabilities of Digital Mars C++. Chapter 23, "Controlling
and Configuring the Debugger," describes the commands you use
when debugging, and the options available in the IDDE for
configuring the debugging environment. Chapter 24, "Commands
Available in Debugging Mode," describes the commands available in
each of the debugging windows.
Debugger Highlights
The integrated debugger:
° Provides a Windows graphical user interface
° Debugs Windows applications under Windows on the
same screen
° Debugs DOS applications running in a DOS box under
Windows 3.1
° Takes advantage of virtual memory, letting you debug
large DOS applications under Windows 3. 1
° Debugs Win32s applications (in the Win32s IDDE,
scw32s. exe) under Windows 3. 1
° Debugs 32-bit Windows and character-mode console
applications (in the Win32 or 32-bit IDDE, scw32. exe)
° Provides a graphical representation of data structures
° Supports high-speed, hardware watchpoints, and
breakpoints
° Lets you drag and drop to execute commands
Choosing an Environment for Debugging
There are three versions of the IDDE included with Digital Mars C++.
An icon for each version you install is available in your Digital Mars
C++ program group. These different versions of the IDDE are
essentially identical, except that they allow you to debug different
kinds of executables:
° To debug a Win32 executable under Windows 95 or
Windows NT, use the Win32 IDDE (SCW32.EXE).
° To debug a 16-bit executable, use the 16-bit IDDE
(SCW. EXE).
° To debug Win32s executables under Win32s, use the
Win32s IDDE (SCW32S. EXE).
Building a Project
To test an application, you must first build the executable file, which
is the file you test. Your project specifies the source and library files
needed to build the executable, as well as options that control the
build process. Windows executables also incorporate such resources
as menus, dialog boxes, icons, and bitmaps; these are defined in
resource files. The building process begins by compiling the source
files into object files. Object files are then linked with library files to
create the executable file.
Selecting the project type
You must specify the type of executable you plan to build. You do
so by choosing Settings from the Project menu and clicking on the
Target tab to select the Target page, as shown in Figure 8-1.
[Figure 8-1 Target page of the Project Settings dialog box]
On this page, choose the operating system your target executable
will run on, and the target type. Not all target types are available
with all operating system types.
The Target page also presents the option of building a Debug or
Release version of the executable. If you want to debug your
executable, select the Debug option.
For more information on the Target page of the Project Settings
dialog box refer to Chapter 15, "More about Projects and
Workspaces."
Setting compiler and linker options for debugging
When you indicate that a debugging version should be built, the
IDDE sets the appropriate compiler and linker options, and also
prevents debugging information already in object files from being
discarded.
To verify that the these settings are appropriate, choose Settings
from the Project menu, and then click on the Build tab to select the
Build page of the Project Settings dialog box. Select the Debug
Information subpage by clicking on that label in the left listbox. The
Debug Information subpage is shown in Figure 8-2.
[Figure 8-2 Debug Information options]
For more information about project, compiler, and linker options,
see Chapter 15, "More about Projects and Workspaces."
Building executable files
The IDDE provides three ways to build executable files from your
project: by performing a standard build, by rebuilding the entire
project, or by linking the existing object files.
Performing a standard build
This is the most common of the three build options. To begin,
choose Build from the Project menu. The IDDE recompiles only
those files that changed since you last compiled them, then links the
project. The IDDE displays any errors in the Output window.
The IDDE Make facility is used by default to determine the steps
needed to build your project. It is functionally identical to the DOS
command-line Make utility SMAKE, included with Digital Mars C++. If
you need to use a different, DOS command-line Make utility, such as
NMAKE or PolyMake, you can do so; see Chapter 16, "More about
Project Build Settings," for details on how to use an external Make
program.
Rebuilding the project
If you want to recompile every file in your project— even those files
that are up-to-date— choose Rebuild All from the Project menu.
The IDDE recompiles all files in your project, whether they've been
edited recently or not, then links the project.
Typical situations in which you use the Rebuild All command
include:
° When you have changed some of the project options
° When you suspect corrupted object .obj files
° When you want to create a final build
Linking the project
If you want to build a program with the existing object files but
without recompiling your source files, choose Link from the Project
menu. The IDDE links the object files.
Typical situations in which you use the Link command include:
° When you have added a new library .lib file
° When you wish to build from object .obj files only
° When you have changed linker options
Other project options
The Build page of the Project Settings dialog box offers additional
settings that you may find useful for precompiling headers and
generating an assembly listing.
Precompiling headers
The Header Files subpage lets you precompile one or all of the
header files that are included by source files in your project.
Precompiling a header is useful when the header file changes
infrequently or not at all between builds, or when a header file is
included by most of the source files in a project. Precompiled
headers speed up the build process, especially with large header
files. For example, windows. h can be beneficially precompiled
because it is large and is not likely to change.
Generating an assembly listing
The Assembly Listing (. COD) check box on the Output subpage lets
you create a .cod file that contains the assembly language code into
which the compiler converts your source code. In this file, C++
source statements are preserved as assembly language comments.
Each commented statement precedes the assembly language code to
which it corresponds.
Running a Project
You can run the application that your project produces without
leaving the IDDE. Commands that run your application ask you to
build it if required.
If your program requires no command-line arguments, choose
Execute Program from the Project menu. The IDDE launches your
application.
If your program requires arguments, first choose Arguments from
the Project menu. The IDDE displays the dialog box in Figure 8-3.
[Figure 8-3 Run Arguments dialog box]
Enter your arguments -- not the program name -- in the dialog box.
For example, entering:
*.* /s
launches your program with the arguments *.* and /s.
After specifying the arguments, click OK. Then run your application
as described above.
Quick Start: Debugging an Application
This section provides a brief description of how to perform common
debugging tasks. You can find a complete presentation of the
debugging capabilities of Digital Mars C++ in Chapter 23, "Controlling
and Configuring the Debugger," and in Chapter 24, "Commands
Available in Debugging Mode." In Chapter 23, see especially the
sections "Commands on the Debug Menu" and "Debug Toolbox
Icons."
After building your project, you can enter debugging mode by
choosing Start/ Restart Debugging (F4) from the Debug menu.
(That is, you may either choose this command from the menu, or
type its keyboard shortcut given in parentheses.) Alternatively, you
can click on the Restart Debugging icon in the Debug toolbox. Any
open Source windows change to debugging mode. Your application
executes to the breakpoint set automatically on WinMain (for
Windows applications) or main (for DOS applications and 32-bit
console applications).
Other debugging windows, such as the Function window and Data/
Object window, can be opened as needed from the Views toolbox
or from the Goto View submenu of the IDDE's Window menu.
In debugging mode, the Start/ Restart Debugging command on the
Debug menu remains available. This command restarts the program.
The Stop Debugging command on the Debug menu exits
debugging mode, and returns the IDDE to editing mode.
Stepping through code
To step to the next source code statement, choose Step Into (F8)
from the Debug menu. Alternatively, you may click on the Step Into
icon in the Debug toolbox. If the current line is a function call, and
debugging information is available for that function, you will trace
into that function. To step over a function call, choose Step Over
(F10) from the Debug menu, or click on the Step Over icon in the
Debug toolbox.
Note
If you accidentally step into a function call when
you meant to step over it, you can move to where
you intended to be— the statement following the
call— by choosing Return from Call from the
Debug menu. This command executes to the
current function's return address (unless a
breakpoint or watchpoint is encountered before
control reaches that point).
Setting and clearing breakpoints
Setting a breakpoint on a source code statement causes your
program to stop when execution reaches that statement. The
debugger regains control, and you may again perform any
debugging mode actions.
To set a breakpoint on a statement, first click on that statement in the
Source window to make it the selected line. Then choose Set/ Clear
Breakpoint (F9) from the Source window pop-up menu (which
appears when you click the right mouse button in the Source
window), or click on the Toggle Breakpoint icon in the Debug
toolbox. These commands act as toggles; repeating them clears the
breakpoint.
The Source window pop-up menu, as it appears in debugging mode,
is shown in Figure 8-4.
[Figure 8-4 Source window pop-up menu in debugging mode]
A breakpoint symbol in the left margin of the Source window
indicates a breakpoint on the adjacent line. You can also clear a
breakpoint by dragging the symbol out of the Source window.
Executing up to a statement
To execute up to the currently selected line, choose Go Until Line
from the Source window pop-up menu. Double-clicking on any line
in the Source window causes your program to run until execution
reaches that line.
Viewing a list of functions
The Function window lists the functions in the current module or in
all modules. Toggle the display by choosing Current Module or All
Modules from the View menu. Double-click on any function to
view that function in a Source window.
You can easily set a breakpoint at the beginning of a function from
within the Function window by choosing the Set/ Clear Breakpoint
(F9) command from the Bpt menu.
Examining the values of variables
The Data/ Object window lets you view either global data or the
variables local to a function. The Show menu of the Function
window has commands Global Data and Local Data that select the
type of data displayed in the Data/ Object window. If you choose
Local Data, the Data/ Object window shows the local variables for
the function currently selected in the Function window, provided
that function is in the call chain. (If a function is not in the call chain,
it has no local data.) The display can also be toggled by choosing
Local/ Global Data from the View menu of the Data/ Object
window.
Examining the call chain
The Call window displays the stack of function calls in your code
that have not yet returned. The list is presented in reverse
chronological order from most to least recent; thus, WinMain (or
main) is at the bottom of the list.
The Call window's Show menu contains commands that let you
zoom in on a particular function in the chain. For example:
° The Source command updates the Source window and
displays the statement that is executing within the
selected function.
° The Data command updates the Data/ Object window
and displays local data for the selected function.
Setting watchpoints
A watchpoint specifies that execution of your program should stop
when a particular variable or memory location is written to or read
from. This capability is essential for detecting problems arising from
wild pointers, for example, which can manifest themselves in
extremely elusive and seemingly random behavior.
Digital Mars C++ debuggers are designed to take advantage of
hardware watchpoints provided by 386 and higher microprocessors.
The Digital Mars C++ installation program may install the file
SCWDEBUG. 386 in the [386Enh] section of system. ini if your
system needs it to allow the use of hardware watchpoints. Because
watchpoints are implemented with hardware assistance, using this
powerful tool imposes no speed penalty on program execution.
Setting a watchpoint on a variable
Using the methods described in the sections above, make sure that
the desired variable is displayed in the Data/ Object window. Click
on the line referencing the variable to select it; the line should be
highlighted. Choose Set Watchpoint (Ctrl+ W) from the Watch
menu of the Data/ Object window. This opens the Set Watchpoint
dialog box, shown in Figure 8-5.
[Figure 8-5 Set Watchpoint dialog box]
The debugger maintains information about the type of variables and
their location in memory. The selected variable's type determines the
size of the watchpoint. The Set Watchpoint dialog box displays the
address and size of the watchpoint as noneditable fields, and
provides options for breaking on a Read access, Write access, or
both. To clear the watchpoint, choose Clear Watchpoint from the
Watch menu of the Data/ Object window.
Warning Exercise caution when setting a watchpoint on an
automatic variable (that is, a local, nonstatic
variable). If you attempt to set such a watchpoint,
the debugger warns you by displaying a message
on the status line. You should clear the watchpoint
by the time the function whose local variable you
are watching returns. If you don't, Windows itself
can use the stack location subsequently, thus
triggering the watchpoint and causing Windows to
crash.
In addition to setting watchpoints on variables, watchpoints can also
be set on locations in memory using the Memory window, whose
Watch menu is identical to that of the Data/ Object window.
Letting your program run until the next breakpoint
You can make your program run until execution reaches a
breakpoint by choosing Go until Breakpoint (F5) from the IDDE's
Debug menu, or by clicking on the Go until Breakpoint icon in the
Debug toolbox. You can use the Breakpoint window to see at a
glance where breakpoints have been set.
Letting your program run until it terminates
You can make your program run until it terminates -- ignoring any
breakpoints -- by choosing Go until End from the Debug menu.
Interrupting execution of the debugged application
Use the Ctrl+Alt+SysRq key combination to break execution of the
application being debugged and return control to the debugger. It
may be necessary to press this key combination a few times before
the debugger regains control. (If you use this key combination to
break execution when control is within Windows itself, it may be
difficult for the debugger to step out of Windows code.)
The technique is most useful when you suspect that your own code
is hung. Returning to the debugger lets you examine your program's
state, which may be one that you thought impossible. Inspecting the
values of variables and the call chain can suggest how to identify
and eliminate the source of the error.
Note
Use Ctrl+Alt+F11 to break execution of Win32s
applications.