I have discovered something strange...
I allocated a memory block:

invoke GlobalAlloc,GMEM_FIXED,size
mov pdata,eax

Then resized it:

invoke GlobalHandle,pdata
invoke GlobalRealloc,eax,newsize,GMEM_MOVEABLE

Ok, this is fixed memory, but the GMEM_MOVEABLE allows it to be moved, but it
stays fixed. This has been discussed on an earlier thread, and is fine for Win95 up.

The problem is, testing on a Win95 system, with 256M RAM, GlobalRealloc fails if
I try to go above about 5M.
I created a loop, calling GlobalRealloc() in 288 byte increments (for reasons that
I won't go into here), and it failed at 59F0E0h, which is 5,894,368 decimal.

So, I wonder why?
I see in an earlier thread that f0dder tested GlobalAlloc() at 256M.
So, why can't I do it with ReAlloc()? Is this perhaps a Win95 specific problem?
Any suggestions welcome.

Barry Kauler
Posted on 2003-03-01 19:29:24 by bkauler
A point of clarification. I am of course reloading the pointer:

invoke GlobalHandle,pdata
invoke GlobalRealloc,eax,newsize,GMEM_MOVEABLE
mov pdata,eax

Also, I understand from MS docs that GlobalHandle() isn't necessary, as a
fixed pointer can be passed direct to GlobalReAlloc().

Anyway, further fascinating developments. I tried this on a Win98 system, and
GlobalReAlloc() failed when the block size reached 599020h or 5,869,600 decimal.
About the same place.

MS has a little utility called "HeapWatch32", and I ran my app. My app is "EVE",
my freeware vector drawing program. I repeatedly imported a JPG graphic file of about 1.5M, and watched what Heapwatch32 reported:

Import 1.5 graphic Bytes alloc Obj cnt Bytes free
1st time 1,710,332 40 7,730,236
2nd time 3,410,684 40 6,029,884
3rd time 5,111,036 40 1,052,179,732
4th time FAIL 5,571,932 40 2,068,325,356

This is reporting the heap allocation specific to my mem block.
Each time I import the JPG, it gets added to the diagram database, and the
mem block increases appropriately. On the third import, it was very slow to
complete, many seconds, and look what has happened in the last column!
Fourth time, sat there for many more seconds before reporting failure, and
again notice the last column.

Can anyone shed any light on this?
What do you think is happening on the last column?

Barry Kauler
Posted on 2003-03-02 03:30:47 by bkauler
I have been using good old Google to find more info.
I found this at MS's MSDN:

Windows Me/98/95: The heap managers are designed for memory blocks smaller than four megabytes. If you expect your memory blocks to be larger than one or two megabytes, you can avoid significant performance degradation by using the VirtualAlloc or VirtualAllocEx function instead.

This is on a page describing GlobalReAlloc() etc.

Funny, that paragraph isn't in my MSDN CD (1998).
They don't tell us that not only does performance degrade, it also fails!

So, I gotta use these Virtual***() thingys -- never tried them.

Barry Kauler
Posted on 2003-03-02 04:35:22 by bkauler
I think if you make a loop with 288 bytes realloc, you will get a large fragmentation of memory.
I know, that windows reallocates a block, it allocates a new one, does a memcopy from old to new and
than frees old block.

I deal with a lot GlobalAlloc alloc'ed blocks also of big size (up to 50MB) and never saw this problem.
Maybe you should not use fixed memory, or simply switch to VirtualAlloc functions.

Main problem without GlobalXX is, that reallocations do not preserve the old memory content.
Posted on 2003-03-03 03:56:34 by beaster
I've also used GlobalAlloc with 5MB+ blocks, and never have had problem with it.
Posted on 2003-03-03 16:35:52 by comrade
My situation is, I am importing a graphic into a database with 288 byte
records, so the graphic gets split into a linked list of records.
I was calling GlobalReAlloc() as I appended each new 288 byte record,
so consider if I am importing a 10M graphic, GlobalReAlloc() gets called
about, what would that be... 90,000 times ... the poor thing falls in a
heap (pun!).

So, I changed my code so GlobalReAlloc() gets called once to increase
the mem block by the total graphic size, then as I create each record don't have to call GlobalReAlloc() repeatedly.
The sensible approach of course.

However, on my Win95 system I'm still getting crashing. Yeah, I was able
to import a 10M graphic, then a couple more smaller ones, then got a crash.
I think we need to head Microsoft's advice not to use the Global***() or
Local***() funcs above about 4M on Win9x systems.
... after all, MS won't be posting that advice for no reason.

Maybe you guys who are doing it ok, are using WinNT/2000/XP?
Posted on 2003-03-03 17:56:44 by bkauler
what if you alloc 2 times and freealloc the smallest one each time?

homemade realloc :|

maybe it has a problem with realloc and not with the normal alloc.

unfortunately I do not have a 9x here so I can not test.

Any specific reason why they can only be 288 bytes? is that faster for your database? :)
Posted on 2003-03-03 18:14:36 by Hiroshimator
I know 288 bytes seem an odd size to choose for database records.
Well, there is some history behind it.
I did build in the capability to make it bigger, but don't want to change
it now, as for sure it'll break something.
When it works, leave it alone.
Maybe one day.
Posted on 2003-03-04 06:58:45 by bkauler