How to Locate Where a General Protection (GP) Fault Occurs
ID: Q133174
|
The information in this article applies to:
-
Microsoft Visual C++ for Windows, 16-bit edition, 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
MORE INFORMATION
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
'<windows directory>\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).
REFERENCES
Dr. Watson: Microsoft Windows Programming Tools, Microsoft Windows
Software Development Kit, 3.1, Chapter 6.
Additional query words:
kbinf 1.00 1.50 4.1 4.10 cv cvw gpf gpf
Keywords : kb16bitonly
Version :
Platform :
Issue type :
Last Reviewed: July 9, 1999