Microsoft KB Archive/42596

From BetaArchive Wiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Knowledge Base


Basic's SETMEM Doesn't Free C Far Allocation; _fmalloc, _ffree

Article ID: 42596

Article Last Modified on 11/21/2006



APPLIES TO

  • Microsoft QuickBasic 2.0
  • Microsoft QuickBasic 4.0
  • Microsoft QuickBASIC 4.0b
  • Microsoft QuickBasic 4.5 for MS-DOS
  • Microsoft BASIC Compiler 6.0
  • Microsoft BASIC Compiler 6.0b
  • Microsoft BASIC Professional Development System 7.0



This article was previously published under Q42596

SUMMARY

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.

MORE INFORMATION

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.
/* Compile this routine with the medium memory model.      */ 
/* Do not compile with the huge memory model, since this   */ 
/* causes the code not to work and the memory won't be     */ 
/* freed.                                                  */ 
/***********************************************************/ 

#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
                


Additional query words: QuickBas BasicCom

Keywords: KB42596