ID Number: Q47958
5.00 5.10 6.00 6.00a 6.00ax
MS-DOS
Summary:
In Microsoft C versions 5.0, 5.1, 6.0, 6.0a, and 6.0ax, the malloc()
family of functions properly reuse the blocks of memory that they
allocate from MS-DOS. The size of a block that malloc() allocates is 8K
bytes by default, but can be modified by assigning a different block
size in bytes to the C run-time library variable "_amblksiz", as noted
on page 33 of the "Microsoft C Optimizing Compiler: Run-Time
Library Reference" version 5.1 manual.
However, for small suballocations of "chunks" (author's terminology)
within an 8K block, previously freed chunks will not be immediately
reused and fragmentation within blocks can occur; this can cause
MS-DOS programs that make many small (for example, 10-byte)
allocations to prematurely run out of memory. This problem occurs
because the "rover" pointer that points to the next chunk of memory to
be allocated points to the memory after the last chunk allocated
without being set to point to the beginning of chunks that were freed.
Reducing the size of allocated blocks by declaring _amblksiz as above
and assigning values under 8096 to it may help reduce fragmentation
within blocks in some cases simply because there is less memory to
lose to fragmentation per block, and your allocations and frees are
more likely to be on reusable block boundaries.
A better alternative is to allocate large blocks yourself, then
perform your own memory management within them to prevent
fragmentation within blocks.
If you have the C run-time library source code (available through
Microsoft End User Sales and Service), you can force the rover pointer
to point at the bottom of the block prior to a memory request as noted
below, so that any adequately large freed chunks will be reused. This
technique will result in executable speed degradation, but will more
fully allocate the last bytes of memory.
More Information:
To change the behavior of the rover pointer to reallocate freed chunks
of memory within a block, make the following change to line 83 of
AMALLOC.ASM, the workhorse module called by malloc() functions:
1. Delete or comment out line 83 with a semicolon (;), as follows:
; mov si,[bx].roveroff; si = starting rover offset
2. Replace the line above with the following two lines:
mov si,[bx].bottom
mov [bx].roveroff,si ;*** put rover at bottom each time
3. Reassemble AMALLOC.ASM with MASM, as follows
masm /Mx /Dmem_L amalloc;
where the /Mx option preserves symbol name case sensitivity, and
/Dmem_L defines the constant to indicate large memory model for
pointers defined by macros in AMALLOC.ASM and other .ASM files used
for the C library. The constant "mem_L" is for large model, "mem_S"
for small, "mem_C" for compact, and "mem_M" is for medium model.
4. Either link with the new AMALLOC.OBJ (and /NOE), or use lib to
replace the module in the appropriate memory model library, as
follows:
lib llibcer.lib -+amalloc;
Additional reference words: 5.00 5.10 6.00 6.00a 6.00ax