Microsoft KB Archive/133174

{|
 * width="100%"|

How to Locate Where a General Protection (GP) Fault Occurs

 * }

Q133174

-

The information in this article applies to:


 * Microsoft Visual C++, versions 1.0, 1.5, 1.51, 1.52

-

SUMMARY
Troubleshooting general protection (GP) faults in a Windows-based application can be a difficult process. This article contains some suggestions and techniques for locating where GP faults occur in C/C++ code.

Using the debugging version of Windows can be helpful in troubleshooting problems in Windows-based applications. For additional information, please see the following article in the Microsoft Knowledge Base:

"Q118891 Installing and Using the Debugging Version of Windows"

What a General Protection (GP) Fault Is
GP faults occur only in the Standard and 386 Enhanced modes of Windows; they cannot occur in the Real mode of Windows version 3.0. A GP fault signifies that something unexpected has happened within the Windows environment, typically an improper memory access. For example, an application or a Windows component might read or write to a memory location that has not been allocated to it (memory that it does not own), potentially overwriting and corrupting other program code in that area of memory.

Another situation where a GP fault may occur involves the passing of parameters between applications and the Windows environment. Invalid parameters can cause invalid instructions to be executed, resulting in GP faults. This is usually the result of an application's internal program code incorrectly passing specific data that could not be correctly interpreted by Windows or a Windows-based application.

How to Find Where a GP Fault Occurs
Fortunately using utilities such as Dr. Watson, CodeView for Windows, and the Visual Workbench debugger can make troubleshooting GP faults a little easier. The .MAP file created by the Visual C++ linker can also be helpful.

If a GP fault occurs and you are not running the application from within a debugger, Windows will display a message box that contains text similar to this:

CALLSDK caused a General Protection Fault in

module CALLSDK.EXE at 0001:02EF.

The address given is the Logical Segment : Offset where the error occurred.

NOTE: The descriptions of the Visual Workbench debugger and CodeView that follow assume your application has been built with debugging information. If you are building the application as a Visual Workbench project, you need to set the build mode to debug in the project options dialog box before building. If you are building the application as an external project, you need to use the /Zi or /Z7 compiler option and the /CO linker option in order to include debugging information when building. If the GP fault occurs in the release (optimized) version of your application, but does not occur in the debug version, you can still use the .MAP file for the application to isolate where the error occurs.

Using the .MAP File
The map (.MAP) file is a list file that the Visual C++ linker can create. It contains information about the executable file that was built. For additional information, please see the following article in the Microsoft Knowledge Base:

"Q80437 Description of the Map File Microsoft LINK Creates" To create a full .MAP file for the project, add the /MAP:FULL option to the linker options for the project in the Miscellaneous category.

To find the function associated with the logical segment : offset pair described in the previous section, you need to look at the "Publics by Value" section of the .MAP file to find its associated symbol. In this section, symbols (publics) are arranged according to their logical segment : offset addresses (as opposed to the "Publics by Name" section, where symbols are arranged alphabetically).

First, locate the logical segment in which the error occurred by matching the digits to the left of the colon in the .MAP file with those given in the GP fault dialog box from Windows. Similarly, locate an offset number that is as close to but less than the offset value given in the GP fault message box. The symbol associated with this logical segment : offset pair in the .MAP file indicates the function where the GP fault occurred.

In a C++ program, the symbol names are usually decorated. The decorated name of the function is listed along with its readable form, which looks similar to a function prototype.

Using Dr. Watson
Before running your application, start the Dr. Watson utility (DRWATSON.EXE) located in your Windows directory. This application will run in the background and generate a DRWATSON.LOG file in your Windows directory. Dr. Watson logs Windows activity. The .LOG file it generates contains important information about any errors that occur in a Windows session.

After a GP fault occurs, double-click the Dr. Watson icon to get a message box that says something like this:

1 new 'Dr. Watson' Failure Reports can be found in file

' \drwatson.log' The DRWATSON.LOG file is a continuous list of errors that have occurred in Windows, so the file may contain information about errors that occurred:


 * In your current session and application.
 * In a previous execution of the application you are trying to debug.
 * In an execution of another application that caused an error.
 * In previous Windows sessions.

The best thing to do is delete or rename the DRWATSON.LOG file before you start debugging your application, so you are sure that the file contains only information relevant to your application.

The most useful part of the file is undoubtedly the "stack dump (stack)" section. Using this information, you can determine the sequence of functions that were called and the function where the GP fault occurred. In addition, Dr. Watson indicates the exact assembler instruction where the failure occurred, and indicates the module information using:

"( module name : logical segment : offset )" NOTE: Dr. Watson is only shipped with Windows and Windows for Workgroups versions 3.1 and later. If you do not have access to one of those versions of Windows, you can still track down GP faults using the debuggers and the .MAP file.

Using CodeView for Windows
CodeView for Windows can be useful in two different ways:


 * If the GP fault does not crash or corrupt Windows, you can simply check the call stack by pulling down the "Calls" menu. The first symbol in the list is associated with the routine that caused the GP fault.
 * If the GP fault crashes Windows but still gives the GP fault dialog box described above, you can use CodeView to set a breakpoint at the address specified by the Logical Segment : Offset pair. This will enable you to prevent Windows from crashing, and you can use the "Calls" menu, as described above. When loading the source into CodeView, you need to view it in mixed source and assembly mode, so you can see the memory addresses associated with the code. The Segment : Offset pairs will be actual addresses, as opposed to logical addresses. Here, you need to note the actual segment address to set the breakpoint correctly.

For example, if the GP fault dialog box says that the error occurred at 0001:0947, and when you load the program into CodeView, the entry point is at 0E4F:0000, you need to set a breakpoint at address 0x0E4F:0x0947 (0E4F:0947). Once the breakpoint is set, you can choose Go from the Run menu or press the F5 key to run the application. It will now break at the point where the GP fault occurs, and you can view the call stack by using the "Calls" menu.

The idea here is to use the call stack to trace the parameters being passed and where memory is being accessed prior to the GP fault. You are looking for places where memory gets overwritten, invalid pointers are referenced, or invalid parameters are passed.

The only problem with this technique is if the GP fault occurs in a module for which there is no debugging information. In this case, you have to set a breakpoint on the first function in the call chain that does have debugging information. Because you cannot see the call stack, the only solution is to step through the code until the GP fault occurs. The goal is to locate the last function with debugging information you saw before the GP fault occurred. Once the function is found, you can set a breakpoint in that function, just before the instruction that causes the GP fault. At this point you should be able to look through the code for the function to determine the cause of the problem.

Using the Visual Workbench Debugger
You can use the Visual Workbench debugger in the same way you use CodeView for Windows. With the project loaded in the Visual Workbench, choose Go from the Debug menu to allow your application to run normally. When a GP fault occurs, the debugger will indicate that and stop the application. If possible, it will stop on the line of code where the GP fault occurred.

It may also display a message box that says "There is no source line debugging information." This indicates that the error occurred in a

function for which you do not have source code (such as a run-time library function) or in some operation that has no relevant source code (such as an assignment or mathematical operation). At this point, you can view the call stack by choosing View Call Stack from the Debug menu. The function that caused the GP fault will be the first symbol listed. Double-click the symbol or click the Go To button to go to the source code for the function that caused the GP fault (if that code is available).