Path: utzoo!attcan!utgpu!news-server.csri.toronto.edu!mailrus!umich!samsung!uunet!microsoft!kensy From: kensy@microsoft.UUCP (Ken SYKES) Newsgroups: comp.windows.ms Subject: Re: No free MS support for SDK; How to use lots of mem in a Win program? Message-ID: <56718@microsoft.UUCP> Date: 19 Aug 90 20:01:57 GMT References: <1990Aug19.132046.24146@eng.umd.edu> Reply-To: kensy@microsoft.UUCP (Ken SYKES) Organization: Microsoft Corp., Redmond WA Lines: 126 In article <1990Aug19.132046.24146@eng.umd.edu> burgoyne@eng.umd.edu (John R. Burgoyne) writes: >PART 2 >^^^^^^ > >The question I am trying to get answered is the following. How do we go about >using large amounts of memory in our programs we develop with SDK version >3.0? I am using MS C compiler 6.0, SDK version 3.0, Windows version 3.0. The >MS Windows SDK book "Tools" says on page 1-3 that the compact and large >models are not recommended for Windows programs because data segments of >programs created with compact or large models are fixed, and because only one >instance of such programs can be run. If anyone can answer any of the >following questions, I would be very happy if you do so. > >Can one use the medium model and have data larger than 64K if it is global? > >Can one use the medium model and have global arrays larger than 64K? The answer to the first two is no. A medium model program has a single data segment. > >Is it ever possible to have arrays larger than 64K? > Well, yes sort of if you use a huge pointer to a chunk of allocated memory (or you use compact/large which is bad - this will limit your program to one instance!!!) See the next question. >What is the general strategy for using lots of memory in a Windows program? > The general strategy is to use GlobalAlloc to allocate the memory you need. The memory should be allocated moveable to avoid heap fragmentation. I think the SDK suggests that it is okay to allocate fixed memory if you are running in protect mode (since kernel can change the selector base without changing the selector.) This gives you the advantage of not having to lock/unlock memory all the time BUT if you want your program to run in real mode this approach should not be used. I will give two examples of allocating a large array - one with moveable memory, one with fixed. Moveable: int huge *hpArray; HANDLE hArray; hArray = GlobalAlloc(GHND, 128000L); hpArray = (int huge *) GlobalLock(hArray); hpArray[10] = 20; GlobalUnlock(hArray); GlobalFree(hArray); hpArray = NULL; Fixed: int huge *hpArray; hpArray = (int huge *) GlobalLock(GlobalAlloc(GHND, 128000L)); hpArray[10] = 20; GlobalUnlock(HIWORD((DWORD) hpArray)); GlobalFree(HIWORD((DWORD) hpArray)); There are a few differences to note in this second piece of code: - The handle was not retained from GlobalAlloc. The Global functions can also take selectors so we pass the selector to the GlobalUnlock / GlobalFree functions. - The memory was initially allocated moveable (GHND) instead of fixed (GPTR.) This is done because fixed memory is PAGE LOCKED in Windows 3.0. This means that the chunk of memory cannot be demand paged to disk - it always sits in physical memory. Needless to say allocating large chunks of page locked memory will bring a system to its knees. So what this code does instead is allocate it as moveable and immediately locks it. This avoids the page lock problem. - There doesn't seem to be any less work in the second piece of code. Well, the difference is in the fixed case you allocate it the first time it is needed and then free it when your done - no global locks/unlocks inbetween. People who write Windows programs know about how tedious locking and unlocking memory all the time can be. - Notice that I didn't check to see if the GlobalAlloc call succeeded. THIS IS BAD BAD BAD!!! In a real program always check memory allocations for success. It was left out to keep the example simple. Another thing to consider is whether some of the memory you allocate can be discardable. This means that the contents of the buffer can be thrown out if nobody has locked the memory down. This is often the case for work buffers. Making them discardable allows windows to free up more memory if it needs to. This will add a little overhead to your program: Whenever a function wants to access the memory it first checks to see if it is present, allocates it if it isn't, then locks it down. The memory is then unlocked when it is no longer needed. More effort yes but it will make you a better neighbor. Just because Windows has protect mode doesn't mean apps should go allocating huge chunks of memory... >Has anyone written a program which uses more than 640K? What are you doing >and how did you do it? > I've written some apps that munge DIBs. It loads the entire DIB into memory, chews on it, and spits it out to another DIB in memory, possibly with intermediate DIBs generated inbetween. This can be quite a large amount of memory, esp. with 24 bit dibs. The technique I used is the fixed memory case mentioned above. The programs are quick and dirty and don't need to run in real mode. >*-----------------------------------------------------------------------------* >| Robert Burgoyne CALCE Center for Electronics Packaging | >| Industrial Liaison University of Maryland | >| burgoyne@eng.umd.edu College Park, MD 20742 | >| (301)-454-0348 USA | >| Compu$erve: 76234,2425 | >| | >| "Improving the quality of electronics hardware through software | >| development and research into physics of failure models." | >*-----------------------------------------------------------------------------* > Ken Sykes No fancy signature, standard disclaimer, etc.