PRODUCT : Borland C++ NUMBER : 1723 VERSION : All OS : DOS DATE : October 25, 1993 PAGE : 1/5 TITLE : Function that returns the total heap memory /* HEAPMEM: Function to return the total amount of memory on the heap. You cannot use coreleft alone because it will only return space from the top of DOS memory down to the last allocated block. If any space has been freed below that last block, but the last block is still in use, then coreleft will not report on the free blocks in this space. The answer is to use heapwalk in combination with coreleft. heapwalk gets all the free blocks below the last allocated block, then coreleft reports on the rest. Tested with Borland C++ 3.1. Can be compiled for any memory model. */ /* Define HEAP_DEBUG when testing fheapmem as a stand-alone application. */ #define HEAP_DEBUG #include #include #include unsigned long heap_avail; long cl, smallest, largest; /* Add this function to your code. Use it instead of coreleft to determine the total amount of heap available, including the heap below the last allocated block. This function also sets its parameters to the coreleft and the size of the smallest and largest blocks available on the heap. Return code less than zero means a heap error has been detected (the negative of return code of heapwalk). A positive return value is the number of bytes available on heap. NOTE: You may leave off the parameters in your version of the fheapmem function. They are not needed to complete the functionality of fheapmem, they are only used here for PRODUCT : Borland C++ NUMBER : 1723 VERSION : All OS : DOS DATE : October 25, 1993 PAGE : 2/5 TITLE : Function that returns the total heap memory an example of what you may do. */ long fheapmem (long *cl, long *smallest, long *largest) { struct farheapinfo fhi; unsigned long ret; int hstat; assert (farheapcheck() != _HEAPCORRUPT); *cl = *largest = *smallest = ret = farcoreleft(); /* Add up all free nodes under last allocated block. */ fhi.ptr = NULL; if ((hstat = farheapwalk (&fhi)) == _HEAPOK) { do { if (!fhi.in_use) { *smallest = fhi.size < *smallest ? fhi.size : *smallest; *largest = fhi.size > *largest ? fhi.size : *largest; ret += fhi.size; } } while ((hstat = farheapwalk (&fhi)) == _HEAPOK); } if (hstat == _HEAPCORRUPT) ret = -hstat; return (ret); } #ifdef __COMPACT__ || __LARGE__ || __HUGE__ /* There is only far heap in these models. */ #define heapmem fheapmem #else /* For near models provide a heapmem which works on near heap. PRODUCT : Borland C++ NUMBER : 1723 VERSION : All OS : DOS DATE : October 25, 1993 PAGE : 3/5 TITLE : Function that returns the total heap memory */ long heapmem (long *cl, long *smallest, long *largest) { struct heapinfo hi; unsigned long ret; int hstat; assert (heapcheck() != _HEAPCORRUPT); *cl = *largest = *smallest = ret = coreleft(); /* Add up all free nodes under last allocated block. */ hi.ptr = NULL; if ((hstat = heapwalk (&hi)) == _HEAPOK) { do { if (!hi.in_use) { *smallest = hi.size < *smallest ? hi.size : *smallest; *largest = hi.size > *largest ? hi.size : *largest; ret += hi.size; } } while ((hstat = heapwalk (&hi)) == _HEAPOK); } if (hstat == _HEAPCORRUPT) ret = -hstat; return (ret); } #endif void show (char *str, long ha, long cl, long sm, long la) { printf ("%s %6ld %12ld %11ld %8ld\n", str, ha, cl, sm, la); } #ifdef HEAP_DEBUG /* main demonstrates use of heapmem. */ PRODUCT : Borland C++ NUMBER : 1723 VERSION : All OS : DOS DATE : October 25, 1993 PAGE : 4/5 TITLE : Function that returns the total heap memory void main (void) { unsigned long heap_avail = 0; char *ba[100]; char *la[10]; int i; long cl, smallest, largest; printf ("* indicates where coreleft alone doesn't show " "newly freed memory\n"); printf (" " "heapmem farcoreleft SMALLEST LARGEST\n"); printf ("====================================================" "=======================\n"); heap_avail = heapmem (&cl, &smallest, &largest); show ("heap at start: ", heap_avail, cl, smallest, largest); /* Allocate some heap. */ for (i = 0; i < 10; i++) la[i] = (char *) malloc (10); heap_avail = heapmem (&cl, &smallest, &largest); show ("heap after first allocation: ", heap_avail, cl, smallest, largest); /* Allocate more memory on heap. */ for (i = 0; i < 100; i++) ba[i] = (char *) malloc (10); heap_avail = heapmem (&cl, &smallest, &largest); show ("heap after second allocation:*", heap_avail, cl, smallest, largest); /* Now free first allocation, thereby creating an area below last allocation that coreleft will not report on as free memory. This is where, using coreleft alone, it looks as if your memory didn't get freed. PRODUCT : Borland C++ NUMBER : 1723 VERSION : All OS : DOS DATE : October 25, 1993 PAGE : 5/5 TITLE : Function that returns the total heap memory */ for (i = 0; i < 10; i++) free (la[i]); heap_avail = heapmem (&cl, &smallest, &largest); show ("heap after first release: *", heap_avail, cl, smallest, largest); /* Free up the rest of memory we allocated on heap. Now coreleft is the same as heapmem because there are no 'holes' below the last allocated block of heap. */ for (i = 0; i < 100; i++) free (ba[i]); heap_avail = heapmem (&cl, &smallest, &largest); show ("heap at end: ", heap_avail, cl, smallest, largest); } #endif HEAP_DEBUG DISCLAIMER: You have the right to use this technical information subject to the terms of the No-Nonsense License Statement that you received with the Borland product to which this information pertains.