Subject: Re: Segmented Memory Woes and Portability 
Distribution: world
Organization: None
Reply-To: chris@chrism.demon.co.uk
X-Mailer: Simple NEWS 1.90 (ka9q DIS 1.19)
Date: Tue, 15 Dec 1992 14:44:19 +0000

In article <wf=Fjj_00WB8QZoUYr@andrew.cmu.edu> ak10+@andrew.cmu.edu writes:

>I naively assumed that all of the segmented memory issues would be
>more or less transparent to me and that the compiler would take care
>of pointer conversions, alignment problems, etc.  I figured if I
>compiled my code with the Compact option, my pointer declarations
>would be interpreted as far pointers and that I could address within a
>1 Mb address space without changing a bit of my code.  This doesn't
>_seem_ to work, though I just started and still don't know very much
>about the 80x86.

Hmmm.  This should work OK.  It *could* be a structure packing problem.

>Alternatively, is it possible to simply call GlobalAlloc() or whatever
>the function is to allocate memory from Windows global heap, convert the handle
>to a far/huge pointer (the pointer declarations somehow declared this way
>implicitly), lock the memory then when you're done with it, convert the
>pointer back to a handle, unlock and free it?  This seems like sensible
>behavior -- assuming that this doesn't force Windows to keep in memory
>stuff that should it should be able to move and swap in/out.
>

Yes - absolutely.  In fact, the standard Windows 3.1 header file
"windowsx.h" contains the macros "GlobalAllocPtr" and "GlobalFreePtr" for
this very purpose.  In Windows 3.1, you're quite safe to keep blocks
of locked memory around - it doesn't adversely affect Windows' ability
to move memory at all.

All you have to remember is to declare your pointers FAR if the item
pointed to is <64k in size, and HUGE if >=64k.  Use FAR pointers unless
you can't avoid it - there are severe computational penalties associated
with the use of HUGE pointers.  One other thing - if you have a pointer to
a HUGE array of items, and the array is >128k in size, each of the items
in the array MUST be exactly a power-of-two number of bytes in size. ie,
16, 32, 64, etc bytes.  Unless you do this, you'll run into horrible
segment wrap-around problems.

For example, you can simply say:

#include <windows.h>
#include <windowsx.h>

double HUGE *x;             // x is a HUGE pointer to array of doubles

// Allocate an array of 50,000 zero-initialized doubles:

x = (double HUGE *) GlobalAllocPtr( 50000*sizeof(double),
                                    GMEM_MOVEABLE | GMEM_ZEROINIT );

....

// Free the memory again.

GlobalFreePtr(x);

>As a programmer, it doesn't seem like I should have to deal with the
>quirks of the processor I'm running on...
>
>My understanding of the 386/486 is that it has better support for virtual
>memory management and that its virtual 32-bit pointers look like contiguous,
>unmoving addressable memory.  Is there a way to do this in Borland C++ 3.1?

What you probably need is "Win32s" - the 32-bit Windows Win32 subset for
Enhanced-mode Windows 3.1.  This lets you run 32-bit applications, each of
which has its own "flat 32-bit" 4GB address space. It's basically a subset
of the Windows NT API that will run on Windows 3.1.  Unfortunately, you
need the 32-bit software development tools supplied with Windows NT in order
to develop Win32s applications, although a free (!) product called
"QuickStart", given away by Phar Lap Software allows these tools to be
run from DOS or Windows 3.1.

>Judging from some of the other posts about memory management, it seems that
>a lot of people might benefit from discussing some of the stuff I've
>brought up.  If this is FAQ material, I'm sorry for clogging network
>bandwith with this message.
>

I think you've raised some interesting points here, which are very worthy
of discussion.

>Drew
>

Chris.
-- 
--------------------------------------------------------------------------
| Chris Marriott                           | chris@chrism.demon.co.uk    |
| Warrington, UK                           | BIX: cmarriott              |
| (Still awaiting inspiration              | CIX: cmarriott              |
|  for a witty .sig .... )                 | CompuServe: 100113,1140     |
--------------------------------------------------------------------------