Document ID:        28811.1
Subject:            WIN: RESOLVING LOW MEMORY PROBLEMS
Last Modifed:       25 September 1996
Author:             CSHAY


Background:
----------

When system resources get low on Windows, erratic behaviors of running
programs often result. Most people believe that the sheer quantity of physical
memory they have is the only important system resource. In fact, most Windows
users typically have plenty of physical memory on their machine, and never use
it all up. There are other, much more sensitive resources that get depleted
first. One of the first resources that gets used up is a special region of
memory which is located just below one megabyte of memory.

Windows relies on DOS for many services. When it needs DOS to do something,
(such as file I/O), Windows switches the processor into "Real Mode", and fires
an interrupt that DOS handles, thereby servicing Window's request.

DOS often needs to share memory with Windows during this process. For
example, many DOS functions need access to a program's PSP (Program Segment
Prefix). DOS is strictly a real mode operating system, and because of this can
only address memory up to 1 Megabyte. Hence, any data it needs to share with
Windows must be located at an address below 1 megabyte.

Some of the memory below 1 megabyte is taken up by whatever you load in
AUTOEXEC.BAT and CONFIG.SYS at DOS boot up time. Even if you use "LoadHigh" or
"DeviceHigh" a chunk of the code will often still be loaded below 1 megabyte.
Also, when Windows starts up it takes some of this memory for it's own Kernel
code, memory manager, and device drivers (such as the keyboard and mouse
drivers). Whatever memory below 1 megabyte that is left over after Windows
starts up is the only memory a Windows application can use when communicating
with DOS. This is generally a quantity smaller than 150k, and the situation is
made much worse if the user loads more than a few things in AUTOEXEC.BAT and
CONFIG.SYS.

Once Windows is running, there are two ways this special area of memory
gets used up. First, each time you start an Windows application, it must
obtain a 512 byte chunk of this memory for a "Task Database" (TDB). This Task
Database contains the aforementioned PSP that DOS needs to share. If it cannot
allocate the 512 bytes, you will get the familiar "Insufficient Memory to Run
This Application" error message. This error message is misleading since most
users think Windows is referring to *extended* memory (that memory *above* one
megabyte) and wonder why they are getting this error when starting up Notepad
on a 32 MB machine.

The second way this memory can be used up is when a .DLL or device driver
requests that their memory be allocated from the "Global Heap" and be "Fixed"
in memory (not able to be moved around by Windows' memory manager). In what is
considered a design flaw in Windows, the Global Heap begins at an address
immediately after the last DOS drivers were loaded (in AUTOEXEC.BAT and
CONFIG.SYS). This means that the Global Heap begins at an address below 1
megabyte. Any .DLL or device driver requesting "FIXED" memory from the Global
Heap will be using up the most precious of resources since Windows can't move
the data elsewhere if it needs the memory for a TDB!

The FIX1MB.EXE utility prevents this by "hooking" the memory allocation
functions in Windows Kernel. Each time an application makes an allocation
request, FIX1MB gets called first. FIX1MB temporarily allocates all of the
memory below  1 MB from the Global Heap. Then it frees just one 512 byte
block. Finally, it gives control back to the memory allocation function.
Therefore, any memory allocated from the Global Heap will come from an address
above 1 megabyte, and there will still be space below 1 megabyte for one TDB
to be allocated (in case the memory allocation is due to the fact that a
program is being loaded). After the memory allocation is done, FIX1MB release
the memory it temporarily allocated.

FIX1MB provides an option to add it to your system.ini. This allows it to
prevent any applications launched at Windows startup time from allocating
memory below 1 megabyte. Keep in mind however that some Windows device drivers
require this special memory, and if you load too many of them in SYSTEM.INI,
it will have the same (negative) effect as loading too many drivers in
CONFIG.SYS or AUTOEXEC.BAT.

There are other system resources that when used up can cause erratic
behavior. Selectors (used up each time a chunk of memory is allocated), and
file handles (allocated for each open file) are two of these. Also, sometimes
there are interrupt conflicts between a device driver and other device drivers
or with DOS itself. These three problems can be eliminated by reducing
the quantity (as opposed to simply worrying about the size) of programs loaded
in AUTOEXEC.BAT, CONFIG.SYS, and SYSTEM.INI.

(For more details on the below 1 megabyte problem and FIX1MB program, read
Matt Pietrek's excellent article on page 79 of the May 1995 Microsoft Systems
Journal.)

Symptoms:
--------

o "Insufficient Memory to Run This Application" error message when no other
   program is running.

o  Slowdown or hanging of the system.

o  General Protection Faults (GPF's) that only occur on certain machines, or
   when the system is under a certain amount of stress (lots of things
   loaded into memory).

o  Corruption of data.

o  Other bizarre, vague, or unusual errors in an application. (a system
   resource allocation failure might not be being handled well by the
   application). Microsoft Access will give the error "7711" in these
   conditions, for example. If you are able to get an ORA error, you should
   first look that error up in your Oracle manual. It may simply be a network
   connectivity problem. On the other hand, data corruption, such as a ORA-900
   caused by your SQL statement being truncated, could indeed be caused by
   low system resources.

o  Some other machines using your version of the program don't reproduce the
   error you are getting after doing the same exact thing you are doing.

Notes About Specific Applications:
----------------------------------

o  Windows for Workgroups 3.11 allocates more memory below 1 megabyte for
   it's drivers than does Windows 3.1 so it is more sensitive to these
   problems.

o  Sql*Net Version 2 can be more resource intensive than SQL*NET V1 so it
   can be informative to check if you are using V2 and then try V1 if you
   have it.

o  Running Windows 3.1 applications on Windows NT or WIN/OS2 are subject to
   all the same limitations discussed in this bulletin.

o  If you are trying to Attach or Import huge tables with Microsoft Access,
   and you get strange errors or hanging after it runs a while, try testing
   it out on a smaller table. If the smaller table doesn't fail you may have
   reached your system's limits. This advice holds for any application
   accessing a huge Oracle table through ODBC. You should follow the advice
   in this bulletin, but keep in mind that you may actually be using up all
   of physical memory if the table is gigantic and ODBC is being used.

What to Do:
----------

1) Obtain FIX1MB. This can be done in three ways:

   a) Anonymous FTP on Internet:
      ftp.microsoft.com
      username: ftp
      password: your email address
      file: /developr/MSJ/MSJMAY95.exe
      Run this file in an empty dos directory to obtain wqa0595.exe.

   b) Compuserve:
      GO MSL-1
      Filename: wqa0595.exe

   c) From Oracle Desktop Support's bbs.
      Filename: MEMORY.EXE

2) Run the self extracting .exe (wqa0595.exe) from an empty DOS directory.

3) From Window's File Manager, run Fix1mb.exe

4) Maximize the icon which should be in the lower left corner of your screen.

5) Hit the "Add to system.ini" button

6) Shutdown windows completely

7) Bring windows back up. The FIX1MB icon should now automatically show up
   on your desktop.

8) Start up the program that has the erratic behavior. (Ignore this step if
   the program won't start up at all)

9) Maximize the icon for Fix1mb

10) If available memory listed in the FIX1MB window is smaller than 60k you
    must remove things from CONFIG.SYS and AUTOEXEC.BAT, reboot and try again.

    You can also try removing Windows device drivers, but that should be a
    last resort.

11) Leave the icon minimized and always running to protect your memory.

Suggestions for Removing Drivers from CONFIG.SYS and AUTOEXEC.BAT:
-----------------------------------------------------------------

(This list is not complete -- the goal to get the number shown by FIX1MB
 to be greater than 60k, while still being able to run your application)

o  Virus Scan drivers - interrupt intensive - not a good idea, at least not
                        when you are trying to track down a resource problem.

o  CD-ROM drivers     - generally not essential, and are large.

o  Sound Card Drivers

o  Disk Compression utilities -- interrupt intensive

o  Network or LAN drivers that are not being currently used.

o  "High Performance" Memory managers, such as QEMM or 386MAX -- a temporary
    solution, but helpful since these are interrupt intensive and can
    "exclude" portions of memory below 1 megabyte from use.

o  SMARTDRIVE -- a temporary solution only. Will really slow things down.

o  MOUSE.EXE - not needed in DOS. Windows already loads it's own.

o  ANSI.SYS

o  SHARE.EXE

o  Anything else that is not essential for running your "testcase"

Note: if you find that you have to permanently unload some drivers that you
sometimes need to use, you could set up a CONFIG.SYS menu. See your DOS
manual.

All of the above drivers may also be being loaded by Windows in the
SYSTEM.INI.  You may want to unload these via Window's Control Panel.