The information in this article applies to:
- Professional and Enterprise Editions of Microsoft Visual Basic,
16-bit only, for Windows, version 4.0
- Standard and Professional Editions of Microsoft Visual Basic for
Windows, versions 2.0, 3.0
- Microsoft Visual Basic for Windows, version 1.0
- Microsoft Windows, versions 3.0, 3.1
- Microsoft Windows for Workgroups, versions 3.1, 3.11
SUMMARY
This article describes steps you can take to determine the cause of and
possibly fix a general protection (GP) fault under Windows version 3.1, or
an unrecoverable application error (UAE) under Windows version 3.0.
MORE INFORMATION
When diagnosing a GP fault, note the address and file where the GP fault
occurred. Sometimes this is a known bug or problem. You can usually use the
address and filename to query the Microsoft Knowledge Base to find a
workaround or resolution.
However, sometimes the GP fault occurs in a range of address locations, so
the specific address won't help. For example, this is the case with a bug
in Visual Basic version 3.0 when using the IIF statement with temporary
strings. This bug can result in a GP fault occurring within one of two
ranges of addresses in VBRUN300.DLL or VB.EXE. For more information on this
bug, please see the following article in the Microsoft Knowledge Base:
ARTICLE-ID: Q127069
TITLE : BUG: GP Faults from Using IIF with Temporary Strings
Dr. Watson logs provide the filename and address of the GP fault, but
otherwise are not helpful in tracking down a GP fault created by a Visual
Basic application.
Typical Causes of GP Faults
If not caused by a bug in the product, GP faults typically occur for one of
the following reasons:
- Calling a dynamic-link library (DLL) or Windows API routine with
incorrect parameters.
A missing ByVal or ByVal used when it should not be can cause either an
immediate or delayed GP fault. To determine if a GP fault or UAE is
caused by custom control or by a call to a Windows API or DLL routine,
remove references to the DLL routine or custom control temporarily. Then
rerun the program to see if the GP fault or UAE still occurs. You may
need to replace such references with statements that simulate return
values.
GP faults that occur in segment 23 of VBRUN300.DLL are more indicative
of calling a DLL incorrectly. For example, you may have forgotten to put
"byval" on a DLL call's string parameter. A typical address looks like
this:
0023:####
The last four digits are not significant (with the exception of the
range of addresses reported for the IIF bug mentioned above).
- Using a faulty DLL routine or custom control.
Corrupted .DLL or .VBX files are not easily identifiable except by
comparing the original from the installation disk with what is currently
on your computer. You may have to manually expand a given .DLL or .VBX
file from the original installation disks, as in this example:
expand A:\VBRUN300.DL_ .\VBRUN300.DLL
This will expand the original VBRUN300.DLL file from the A: drive into
the current directory. You can then compare date and size with the
original file in your \WINDOWS\SYSTEM directory. Before replacing the
current (original) VBRUN300.DLL in the \WINDOWS\SYSTEM directory, back
it up by renaming or copying it.
Chapter 25 of the Programmers Guide lists files required for any given
Visual Basic version 3.0 program. Programs making use of the Microsoft
Jet 2.0/Visual Basic 3.0 Compatibility Layer need to reference the
ACC2COMP.TXT file that comes with the compatibility layer to see a list
of additional files. The same is true for those using the Microsoft
Access version 2.5 Service Pack.
Check with the vendor of any custom control you are using. There may be
an update available that fixes problems you are encountering.
- Loading corrupted Visual Basic forms or modules. (The workaround for
this is given later in this article.)
- Using a corrupted .FRX file. Microsoft has received reports but has been
unable to fully confirm that a corrupted .FRX file can cause a GP fault.
Files with the .FRX extension are what Visual Basic uses to store
bitmaps, icons, and graphics for a given form. If the contents of this
file are ruined, the GP fault would occur (most likely) during the form
load process.
You may need to rebuild your .FRX file by deleting the .FRX file for the
form in question. This will cause your form to lose any icons, bitmaps,
or metafiles it was using, so you'll need to restore each of them, which
will rebuild the form's .FRX file. Before deleting the .FRX file, ensure
that you have separate copies of any icons, bitmaps, or metafiles used
to create the form. It is good practice to keep backup copies of these
files for any form you create, so you can easily recreate the form if
necessary.
- Not doing a "clean compile." Microsoft has received reports but has not
been able to confirm that building an .EXE file only after starting
Visual Basic will reduce otherwise untraceable GP faults. There is a
known problem with the size of an .EXE file growing after each compile
while within a single Visual Basic session. It has not been demonstrated
or conclusively proven that this can introduce GP faults. Doing a clean
compile may be treating the symptom rather than the actual problem, but
some users have had success with it.
For more information about the known problem with the size of an .EXE
file growing after each compile, please see the following article in the
Microsoft Knowledge Base:
ARTICLE-ID: Q119734
TITLE : BUG: Recompiling VB Project May Produce Larger .EXE File
Calling an external function in a DLL with a string argument and not
providing a string large enough for the function to modify.
A typical example of this is calling one of the Windows API profile
string functions such as GetProfileString. If the string you pass is
smaller than what will be returned, Windows will overwrite the string
heap and this eventually will lead to a GP fault when Visual Basic
attempts to perform string management. Typically, string management such
as heap compression will occur when the current routine is exited or if
you try to allocate a string that is larger than the largest block of
available string memory.
You can get around this limitation by padding the string with additional
characters before using it. You may later need to trim the additional
characters or the string size may be different from what you expected.
For example:
strToPass$ = Space$(255)
' ret is # of characters assigned to strToPass$
ret = CallExternalRoutine(strToPass$, ...)
actualStr$ = mid$( strToPass$, 1, ret )
External Factors That May Influence a GP Fault
GP faults are not always consistent. If the problem is intermittent across
different computers, analyze the answers to these questions:
- What device drivers are loaded?
- What TSR programs are loaded?
- Are different computers using different versions of Program Manager?
- On which version of MS-DOS or Windows does the problem occur?
- What kind of video display is used by each computer? If you switch to
the default Windows VGA display that comes with Windows, does the
problem go away? If so, you may need an update to the video driver you
are using, or there may be a bug in a custom control you are using that
causes it to fail at higher resolution or palette sizes.
Steps to Follow When You Get a GP Fault
- Always exit Windows after the GP fault. However, before exiting, note
which programs were loaded in memory and what actions were taken that
ended in the GP fault. The hope is that this paper log will help you
identify a pattern for troubleshooting.
- See if the same procedure repeats the problem (likely).
- Use the Chkdsk or Scandisk utility to make sure your hard disk is
healthy and clean.
- Check for viruses.
- Press CTRL+ESC to bring up the task list. Is anything in there? Close it
all out if there is. Better yet, rename your Startup group by pressing
ALT+ENTER in Program Manager; name it something like Xstartup. Then
restart Windows, start Visual Basic, and run your application. Does the
problem go away? If so, it may mean that something else is interfering
or conflicting that results in the GP fault.
A GP fault may be a problem in the code, or it may be a symptom of some
other situation. The key is to localize and repeat the conditions that
resulted in the GP fault in order to better diagnose it. When you can
isolate the minimum activities, programs, and external factors influencing
a GP fault, you can determine if it is a problem with your code or
something else.
Steps to Clean Code
To determine if a GP fault or UAE is caused by corrupted code, save the
code in your forms and modules as text. Then load the code as text. This
process cleans the internal representation of the code (P-code).
In Visual Basic 3.0:
- In the Project window, select the form or module to clean.
- On the File menu, click Save Text, and click OK.
- On the File menu, click View Code.
- On the File menu, click Load Text, select the same file, and click
Replace.
To determine if a GP fault or UAE is caused by a corrupted form, recreate
the form. To recreate a form, add a new form to your project, and place
new controls and menus on it to match the old form. Copy the code by saving
code as text from the old form and loading as text into the new form.
Finally, remove the old form, and rename the new form.
Steps to Recreate Form
In Visual Basic 3.0:
- On the File menu, click Add Form. Add the same controls and menus
to this new form as are on the old form.
- In the Project window, select the old form or module.
- On the File menu, click Save Text, and click OK.
- On the File menu, click Remove File.
- In the Project window, select the new form.
- View the code from the Project window or by clicking Code on the View
menu.
- On the File menu, click Load Text. Select the same code text file,
and click Replace.
- Set the new form Name property to the old form's value.
You can also clean a project file (.MAK or .VBP file). Start a new project,
and then add all the forms and modules to the new project.
|