PRODUCT : Borland C++ NUMBER : 649 VERSION : 2.0 OS : PC DOS DATE : September 11, 1991 PAGE : 1/7 TITLE : Common Causes of General Protection Faults WHAT? GENERAL PROTECTION ERROR! Protected mode development tools permit much larger programs to be compiled faster than their real mode counterparts. They accomplish this by allowing the use of a vastly larger memory area than is available to real mode tools. There is a cost for this increased capability, however; many of us will have to change the coding practices and strategies we grew to depend on with the relatively tolerant real mode development tools. Central to this change is the increasingly notorious "General Protection Fault." A GP Fault is generated by what one might think of as a debugger built into the CPU and is enabled any time a program is operating in protected mode. This debugger-in-a-CPU is very, very uncompromising with regard to the rules which a program must obey while availing itself of protected mode capabilities. For example, suppose a block of memory is allocated for use. Further suppose that we code an errant read or write outside this block. In real mode this may show up in a variety of more-or- less unacceptable ways; many of these we can choose to ignore. The same program executed in protected mode will, in all probably, display a General Protection Fault error message and immediately exit to DOS. This illustrates the cost of operating in protected mode; our right to ignore coding problems is seriously limited. There is an upside to this, however: any program that runs for any length of time in protected mode is likely to be far more bug free than an equivalent program executed only in real mode. General Protection Faults are generated, however, by more than just reads or writes outside proper memory areas. The following list, extracted from the Intel 386 Programmer's Reference Manual, serves to suggest the level of "protection" which we may expect while operating in protected mode: ----------------------------------------------------------------------- PRODUCT : Borland C++ NUMBER : 649 VERSION : 2.0 OS : PC DOS DATE : September 11, 1991 PAGE : 2/7 TITLE : Common Causes of General Protection Faults All protection violations which do not cause another exception cause a General-Protection Fault. This includes (but is not limited to): a. Exceeding the segment limit when using CS, DS, ES, FS, or GS segments b. Exceeding the segment limit when referencing a descriptor table c. Transferring execution to a segment which is not executable d. Writing to a read-only data segment or a code segment e. Reading from an execute-only code segment f. Loading the SS register with a selector for a read-only segment (unless the selector comes from a TSS during a task switch, in which case an invalid-TSS exception occurs) g. Loading the SS, DS, ES, FS, or GS register with a selector for a system segment h. Loading the DS, ES, FS, or GS register with a selector for an execute-only code segment i. Loading the SS register with the selector of an executable segment j. Accessing memory using the DS, ES, FS, or GS register when it contains a null selector k. Switching to a busy task l. Violating privilege rules m. Exceeding the instruction length limit of 15 bytes (this only can occur when redundant prefixes are placed before an instruction) n. Loading the CRO register with a set PG bit (paging enabled) and a clear PE bit (protection disabled) PRODUCT : Borland C++ NUMBER : 649 VERSION : 2.0 OS : PC DOS DATE : September 11, 1991 PAGE : 3/7 TITLE : Common Causes of General Protection Faults o. Interrupt or exception through an interrupt or trap gate from virtual-8086 mode to a handler at a privilege level other than 0 p. The general-protection exception is a fault. In response to a general-protection exception, the processor pushes an error code onto the exception handler's stack. If loading a descriptor causes the exception, the error code contains a selector to the descriptor; otherwise, the error code is null. The source of the selector in an error code may be any of the following: 1. An operand of the instruction 2. A selector from a gate which is the operand of the instruction 3. A selector from a TSS involved in a task switch ----------------------------------------------------------------------- PROGRAM OR DEVELOPMENT TOOL? Obviously if your applications are going to be subject to GP Fault errors it stands to reason that the development tools themselves must abide by the same rules and are subject to this demanding debugger-in-a-CPU. It is unlikely that any significant program has ever been bug- free and Borland's development tools are no different. As you might expect, we are dedicated to eliminating any bugs that can be identified. One might guess that this would be an easy task. Unfortunately the protected mode mechanism does not distinguish between problems in the code being developed under the tools and problems with the tools themselves. Consequently, it becomes necessary for the developer to take additional steps to assure that their code is not the cause. Although there is little that Borland can do to make this process easier, we can supply you with a list of known problems in the BC++ tools that generate reproducible GP Fault errors. If you find a problem you are encountering on this list you can eliminate your program as the culprit. PRODUCT : Borland C++ NUMBER : 649 VERSION : 2.0 OS : PC DOS DATE : September 11, 1991 PAGE : 4/7 TITLE : Common Causes of General Protection Faults - Moving the mouse while BCX is setting up to run your program can cause a GP Fault. This can happen if the mouse is moving when BCX switches from compiling to linking also but not nearly as often as choosing RUN|RUN and moving the mouse after the link or dependency check. - Window Resize/Move- Clicking the mouse almost anywhere outside of a BCX window set up for resizing or moving (green bordered) - Using the ,m (memory dump) option in a BCX watch window - Doing a Repaint Desktop in BCX with a HERCULES card attached (and any video cards doing Hercules simulation) - Compiling a program under BCX using the ternary operator with the second or third variables undefined - Compiling a program with the OPTIONS|DIRECTORY|INCLUDE box filled to its maximum - Inspecting on a static member of a class with the BCX debugger - Compiling the DLLDEMO examples program under BCX using different segment names for BSS or DATA Ok, so the problem can't be in your application because you have reduced it to the point where all it does is print "Hello, world" and it's still giving you a GP Fault; and it's not on the list of known problems. There are two final sources of General Protection Faults that have little to do with either the tools or the application under development; the Operating System configuration, the configuration of the hardware and, on occasion, the hardware itself. OPERATING SYSTEM CONFIGURATION? GP Faults generated by OS configuration are not uncommon. Most of them find their cause in the variety of memory management PRODUCT : Borland C++ NUMBER : 649 VERSION : 2.0 OS : PC DOS DATE : September 11, 1991 PAGE : 5/7 TITLE : Common Causes of General Protection Faults standards (or lack thereof) which characterize use of extended and expanded (EMS) memory. Since the advent of the IBM PC the industry has progressed from the total absence of a standard, as exemplified by IBM's VDISK, through VCPI to today's most likely candidate, the DPMI standard. However, even DPMI remains unfinished at revision 0.9. As you might guess, writing a development tool or application which will not clash with any potential user of memory is very difficult, if not impossible, to do without an industry-accepted memory standard. To resolve these inevitable incompatibilities, the user is at the mercy of the contending utilities. If they can be manually configured to avoid conflict, the problem can be resolved; otherwise, the user must assure they they are never loaded at the same time. Many modern utilities (e.g., QEMM & MAX386) provide the options necessary to resolve such contentiousness. Many older utilities (e.g., VDISK) do not. To quickly eliminate OS configuration (device drivers, TSR's, etc.) as a source of difficulty, simply boot your computer from a vanilla DOS disk. If a vanilla DOS disk isn't available, rename your system's CONFIG.SYS and AUTOEXEC.BAT to something else (e.g., CONFIG.TMP and AUTOEXEC.TMP) and reboot your computer. Note that "vanilla" means without any drivers or TSR's INCLUDING the mouse driver. For some of us, running for any length of time without a mouse is excruciating; you will simply have to grin and bear it for a short time. Now execute the offending process; if the problem persists, contact Borland Technical Support (see final section for procedures). If the problem seems to have been eliminated, however, you will need to begin the tedious but rather undemanding process of identifying the offending driver/TSR through stepwise restoration of your normal operating configuration. PRODUCT : Borland C++ NUMBER : 649 VERSION : 2.0 OS : PC DOS DATE : September 11, 1991 PAGE : 6/7 TITLE : Common Causes of General Protection Faults HARDWARE DEPENDENCIES? Finally, there are some GP Fault problems which cannot be resolved without replacing the computer or some part of the computer. Often the problem revolves around the system BIOS or some unique aspect of the computer's architecture. For instance, a problem that occurs often enough to be well known involves GP Faults generated when the UPARROW and DOWNARROW keys are pressed with NUM LOCK enabled. For some computers, the manufacturer provides a ROM BIOS update which solves the problem. In addition, any 80x286 based computer is more likely to be affected by GP Fault errors in protected mode than are 80x386 or 80x486 computers. This is largely due to the speed with which these computers can switch between protected mode and real mode. For instance, use of a mouse in protected mode represents hundreds of protected/real mode exchanges per second; any failure on the part of the hardware to realize this demand will inevitably result in a GP Fault error. Identification of this type of problem usually requires running the failing installation on a different computer, trying to change as little as possible. Although such "in vivo" testing is unlikely to be absolutely conclusive, it will often serve as a tiebreaker for a final decision. REPORTING A GENERAL PROTECTION FAULT PROBLEM Assuming that the problem is independent of the program you are developing, occurs under a vanilla operating system as well as under your normal operating system configuration and is not on the list of known GP fault problems, it is time to contact Borland Technical Support. When contacting Technical Support regarding a GP Fault, it will be most efficient if you have the following information available: 1. A set of steps to reproduce the problem (including any code that may be required) 2. A description of the problem PRODUCT : Borland C++ NUMBER : 649 VERSION : 2.0 OS : PC DOS DATE : September 11, 1991 PAGE : 7/7 TITLE : Common Causes of General Protection Faults 3. The GP information which was displayed just prior to the exit to DOS. It looks like: GP at 0020 0FC8 The following information may also be requested by the Technical Support Engineer, depending on the problem: 4. BIOS date, manufacturer and revision 5. Computer make and model 6. Memory configuration 7. Operating system revision 8. Graphics adapter make, model and Video BIOS revision/date