Debugging Windows programs can be a challenging experience. Objects move around in memory. The thread of execution can be a twisting maze where it is difficult to know what code is executing or to control what code in your program is executed.
This section describes the WLH and WGH commands that you use to examine movable memory objects by their handles. It also describes ways to control your application's execution, how to interrupt and resume debugging your application, how to handle abnormal termination from fatal errors and general protection faults, and how to resume debugging your application after a normal termination.
In a Windows application, the LocalLock and GlobalLock routines are used to lock memory handles so that they can dereference them into near or far pointers.
In a debugging session, you may know the memory object's handle. However, you may not know what near or far address the handle references unless you are debugging in an area where the program has just completed a LocalLock or GlobalLock routine call. To get the near and far pointer addresses for unlocked local and global handles, use the WLH and WGH commands.
For detailed information on the WLH and WGH commands, see “WGH (Windows Dereference Global Handle)” on page 463 and “WLH (Windows Dereference Local Handle)” on page 466.
Controlling Application Execution
In CVW, all of the CodeView execution commands (Go, Program Step, Trace, and Animate) can be used to control your application's execution. However, you should keep these restrictions in mind while using CVW:
Attempting to use the Program Step or Trace commands to execute Windows startup code in Assembly mode causes unpredictable results. To step through your application in Assembly mode, first set a breakpoint at the WinMain routine and begin stepping through the program only after the breakpoint is taken.
Directly calling a Windows application procedure or dialog routine in the Watch window, in the Quick Watch dialog box, or with the Display Expression (?) command can have unpredictable results.
The rest of this section describes techniques and special considerations for controlling program execution in CVW.
There may be times when you want to halt your program immediately. You can interrupt your program by pressing CTRL+ALT+SYSREQ. After you press CTRL+ALT+SYSREQ, CVW gains control and displays code corresponding to the current CS:IP location. You then have the opportunity to examine registers and memory, set breakpoints and watch expressions, and modify variables. To resume execution, use one of the CodeView program execution commands.
Summary: Don't step or trace system code.
You should take care when you interrupt execution. If you interrupt execution while Windows code or other system code is executing, attempting to use the Program Step or Trace commands can produce unpredictable results. When you interrupt execution, it is safest to set breakpoints in your code and then resume continuous execution with the Go command, rather than using the Program Step, Trace, or Animate commands.
For example, an infinite loop in your code presents a special problem. Since you should avoid using the Program Step or Trace commands after interrupting your application, you should try to locate the loop by setting breakpoints in places you suspect are in the loop, then resume continuous execution. When one of these breakpoints is taken, you can be sure that the currently executing code is your application code.
At times (such as when your application is executing an infinite loop), you may have to terminate the application. The Windows Kill Application (WKA) command terminates the currently executing task. Since this task is not necessarily your application, you should use the WKA command only when your application is the currently executing task.
If your application is the currently executing task and is executing a module containing CodeView information, the Source window highlights the current line or instruction. However, if your application contains modules that are compiled without CodeView information, it is more difficult to determine whether the assembly-language code displayed in the Source window belongs to your application or to another task.
Summary: Use the WDG command to find out which task terminated.
In this case, use the Windows Display Global Heap (WDG) command with the value in the CS register as the argument. CVW displays a listing that indicates whether the code segment belongs to your application.
If the current code is in your application, you can safely use the WKA command without affecting other tasks. However, the WKA command does not perform all the cleanup tasks associated with the normal termination of a Windows application. For example, global objects created during program execution but not destroyed before you terminated the program remain allocated in the system-wide global heap. This reduces the amount of memory available during the rest of the Windows session. For this reason, you should use the WKA command to terminate the application only if you cannot terminate it normally.
Note:
The WKA command simulates a fatal error in your application, causing Windows to display an Unexpected Application Error message box. After you close this message box, Windows may not release subsequent mouse input messages from the system queue until you press a key.
If this happens, the mouse pointer moves on the Windows screen, but Windows does not respond to the mouse. After you press any key, Windows responds to the queued mouse events.
Handling Abnormal Termination of the Application
Your application can terminate abnormally in one of two ways while you are debugging it with CVW. It can cause a fatal exit, or it can cause a general protection fault. In both cases, CVW gains control, giving you the opportunity to examine the state of the system when your application terminated. CVW allows you to view registers, display the global and local heaps, display memory, and examine your source code.
Handling a General Protection Fault
If the abnormal termination is caused by a general protection fault (GPF) while executing your application code, CVW displays the line of code where the error occurred. Also, the Command window displays the following message:
Trap 13 (0DH) -- General Protection Fault.
If the general protection fault occurred while executing Windows code, the CVW Command window displays a stack trace that is useful for finding the error in your source code.
Restarting a Debugging Session
You can terminate your application without leaving CVW. Windows notifies CVW that it is terminating the application, and CVW displays the following message:
Program terminated normally (0)
The value in parentheses is the return value of the WinMain routine. This value is usually the wParam parameter of the WM_QUIT message, which in turn is the value of the nExitCode parameter passed to the PostQuitMessage routine.
You can then use the Go command to continue the debugging session for additional DLLs or applications. You can also restart the application by using the Restart command on the Run menu.