Click Here!
home account info subscribe login search My ITKnowledge FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
To access the contents, click the chapter and section titles.

Fast Track Visual C++ 6.0 Programming
(Publisher: John Wiley & Sons, Inc.)
Author(s): Steve Holzner
ISBN: 0471312908
Publication Date: 09/01/98

Bookmark It

Search this book:
 
Previous Table of Contents Next


Chapter 7
32-Bit Memory Handling

In the old days of DOS, memory was restricted to 1MB, and of that 1MB, only 640K was usable. When Windows came along, the earliest versions still ran in 1MB. Eventually, that limit began to fall. As processors improved, Windows 3.1 was able to access up to 16MB, but when users started running several programs at the same time, even 16MB wasn’t enough. With the introduction of 32-bit Windows—Windows 95—the operating system could address 4GB, or 4,294,967,296 bytes. That’s enough to keep us going for a long time (in fact, you can only use 2GB–4MB in Windows 95 and 98, but that’s still quite a lot).

In this chapter, we present an overview of memory and then go to work allocating virtual memory, scanning all of memory to see what’s there, and learning how to share memory between two running processes. Putting all this into action will expose us to a tremendous amount of memory power.

Overview of Memory

With 32 bits, pointers to memory can now range from 0x00000000 to 0xFFFFFFFF. In fact, each individual process gets a 4GB address space, though it’s hard to imagine a computer today with that much physical memory; instead, computers use virtual memory. Virtual memory is the memory that can spill over to disk when needed, and is swapped back into real memory (RAM) when needed.


Where Is the Windows Operating System?

The actual Windows operating system and DLLs are stored in very high memory, and though it is possible to overwrite them by mistake in Windows 95 and 98, you can’t do that in Windows NT, which is one reason NT is more robust.


Let’s take a look at memory, section by section, in Windows 95 and 98. The very bottom 64K of memory, from 0x00000000 to 0x00000FFF is reserved for NULL pointers. This region is taboo: If a pointer points to this region, Windows assumes it’s invalid and issues a NULL pointer error.

All the memory from the very bottom up to the end of the first 4MB is reserved for the system—largely to maintain compatibility with Win16 programs, which place a lot of system code there—so our programs are actually loaded at the address 0x00400000. We have all the space from there to 0x7FFFFFFF with which to work. Above that region (starting at 0x80000000) is the Windows system itself.

Starting at 0x80000000 are the system DLLs (like USER.DLL); that section of memory goes up to 0xBFFFFFFF. Right after that location, starting at 0xC0000000 and continuing to the top of memory 0xFFFFFFFF, is where the operating system is, along with the virtual device drivers.

The following is a graphical overview of how memory is set up:

                 --------------------------------------
                |0xFFFFFFFF                          |
                |                                    |
                |       Operating system             |
                |       Virtual device drivers       |
                |                                    |
                |0xC0000000                          |
                |--------------------------------------      |
                |0xBFFFFFFF                          |
                |                                    |
                |       WIN32 DLLs                   |
                |                                    |
                |                                    |
                |0x80000000                          |
                |--------------------------------------      |
                |0x7FFFFFFF                          |
                |                                    |
                |       User programs                |
                |                                    |
                |                                    |
                |0x00400000                          |
                |--------------------------------------      |
                |0x003FFFFF                          |
                |                                            |
                |    16-bit Windows (compatibility)          |
                |                                            |
                |                                            |
                |0x00001000                          |
                |--------------------------------------      |
                |0x00000FFF                          |
                |                                    |
                |  NULL pointer assignments          |
                |  16-bit Windows (compatibility)    |
                |                                    |
                |0x00000000                          |
                 --------------------------------------

Not all this memory is in your machine; often, Windows sends memory out to disk as virtual memory. Windows keeps a paging file on disk for just this purpose, and memory is divided into pages to make memory handling easier (the page size in Windows 95 and 98 is 4K).

Now that we’ve had an overview of memory, we look at some of the functions Visual C++ provides for us to work with when handling memory.

Powerful Memory Functions

The GetSystemInfo() function is a good place to start. This function fills a structure of type SYSTEM_INFO, which includes the minimum and maximum application addresses and the page size as shown in the following example:

        typedef struct _SYSTEM_INFO { // sinf
            union {
                DWORD  dwOemId;
                struct {
                    WORD wProcessorArchitecture;
                    WORD wReserved;
                };
            };
            DWORD  dwPageSize;
            LPVOID lpMinimumApplicationAddress;
            LPVOID lpMaximumApplicationAddress;
            DWORD  dwActiveProcessorMask;
            DWORD  dwNumberOfProcessors;
            DWORD  dwProcessorType;
            DWORD  dwAllocationGranularity;
            WORD  wProcessorLevel;
            WORD  wProcessorRevision;
        } SYSTEM_INFO;

The powerful VirtualQuery() function lets us take a look at a specific region of memory. Using this function, we can find the base address of an allocated region of memory as well as the size of the region. This and other information are stored in a structure of type MEMORY_BASIC_INFORMATION, which looks like this:

        typedef struct _MEMORY_BASIC_INFORMATION { // mbi
            PVOID BaseAddress;            // base address of region
            PVOID AllocationBase;         // allocation base address
            DWORD AllocationProtect;      // initial access protection
            DWORD RegionSize;             // size, in bytes, of region
            DWORD State;                  // committed, reserved, free
            DWORD Protect;                // current access protection
            DWORD Type;                   // type of pages
        } MEMORY_BASIC_INFORMATION;
        typedef MEMORY_BASIC_INFORMATION *PMEMORY_BASIC_INFORMATION;


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.