Article: Q42596
Product(s): See article
Version(s): 4.00 4.00b 4.50
Operating System(s): MS-DOS
Keyword(s): ENDUSER | SR# S890227-157 B_BasicCom S_C S_QuickC | mspl13_basic
Last Modified: 21-DEC-1989
When reducing far-heap size with the SETMEM statement in BASIC and
then calling a Microsoft C or QuickC function that does a far
allocation, the reduced far-heap memory is not recoverable with SETMEM
after returning to the QuickBASIC program. C routines do far-memory
allocation with "_fmalloc" and "_ffree" functions. This is expected
behavior for the following reasons:
1. The C _fmalloc obtains memory from MS-DOS. Once far memory is
obtained by a C program, it becomes part of the C far heap.
2. The _ffree does not release the memory back to MS-DOS, but rather
stores it in the C far heap along with a linked-list data structure
that C uses to manage its heap space.
Thus, SETMEM cannot recover this memory.
This information applies to Microsoft QuickBASIC Versions 4.00, 4.00b,
and 4.50 for MS-DOS, to Microsoft BASIC Compiler Versions 6.00 and
6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00
for MS-DOS and MS OS/2.
To recover the memory in the BASIC program, the C routine should do a
huge allocation with the "halloc" and "hfree" functions. The C huge
allocation routines differ from the far allocation routines. The
halloc function always requests the memory directly from MS-DOS. The
hfree function returns the memory directly back to MS-DOS. Once a C
routine has executed an hfree, this memory can be recovered from a
BASIC program with SETMEM.
There is one disadvantage to using huge allocation. With huge
allocation, there is no memory management involved on the part of the
C routines. This can lead to memory fragmentation if the C routines do
repeated allocations and frees.
The C routine should be carefully constructed to avoid this
fragmentation. For more information on C memory management, please see
Page 114, "Memory Management: A Two-Step Process," "The Waite Group's
Microsoft C Bible."
Code Example
------------
/***********************************************************/
/* The following C function HugeMemTest can be called from */
/* BASIC to demonstrate that huge allocation returns */
/* memory to the BASIC program. */
/***********************************************************/
#include <stdio.h>
#include <malloc.h>
void
HugeMemTest(void)
{
long huge *lalloc;
printf("Inside of C routine\n");
lalloc = (long huge *)halloc(10000L,sizeof(long));
if (lalloc == NULL)
printf("\nInsufficient memory available\n");
else
printf("Memory successfully allocated\n");
hfree(lalloc);
printf("Leaving C routine\n");
}
'***********************************************************
'* This BASIC routine releases memory to DOS using *
'* SETMEM. It then calls a C routine that does huge *
'* allocation and a huge free. SETMEM is used to recover *
'* the memory and success or failure is reported. *
'***********************************************************
DECLARE SUB HugeMemTest CDECL ()
' Report far heap size before the C call.
CLS
BeforeCall = FRE(-1)
PRINT "AVAILABLE MEMORY ON THE FAR HEAP: ", BeforeCall
Storage = SETMEM(-50000)
PRINT "SIZE OF FAR HEAP AFTER SETMEM: ", FRE(-1)
' Call to the C routine
PRINT
CALL HugeMemTest
PRINT : PRINT : PRINT : PRINT
' Report far heap size after call to C.
PRINT "SIZE OF FAR HEAP AFTER CALL TO C: ", FRE(-1)
Storage = SETMEM(50000)
AfterCall = FRE(-1)
PRINT "AVAILABLE MEMORY ON THE FAR HEAP : ", AfterCall
' Report success or failure.
IF AfterCall <= BeforeCall THEN
PRINT "SETMEM FUNCTIONED PROPERLY"
ELSE
PRINT "SETMEM DID NOT FUNCTION PROPERLY"
END IF
END