PRODUCT : Borland C++ NUMBER : 1008 VERSION : 3.0 OS : DOS DATE : October 19, 1993 PAGE : 1/4 TITLE : allocmem VS. malloc FUNCTION: Allocates DOS memory segment. SYNTAX: #include int allocmem(unsigned size, unsigned *segp); RETURN: allocmem returns -1 or success. In the event of error, allocmem returns a number indicating the size in paragraphs of the largest available block. NOTES: This functions allocates a block of memory using DOS's memory allocation function, int 21h, function 48h. All allocated blocks are segment aligned. The reference guide states that malloc's and allocmem's cannot be used in harmony with one another. While this is not necessarily true it is included to deter programmer's from stabbing themselves in the back due to a lack of knowlege about how the memory allocation routines actually work. When a Turbo C++ program runs, it always resides inside a single DOS memory block. If more memory is needed to allocate a block from the far heap, the memory block is expanded to fit the need. --------------- 640K -------------- | DOS Free | | DOS Free | | Memory | | Memory | | | -------------- | | | Far Heap | \ --------------- | | \ | Far Heap | | | | | ............| |............| |- Program remains inside | TC++ | | TC++ | | a single block which is | Program | | Program | / resized to fit allocation. | | | | / --------------- -------------- | DOS | | DOS | | | | | --------------- -------------- Before farmalloc() After farmalloc() If allocmem() is called, a separate block is allocated for the memory requested. By default, this block will be the next higher block in memory above your program. As a result, if you attempt PRODUCT : Borland C++ NUMBER : 1008 VERSION : 3.0 OS : DOS DATE : October 19, 1993 PAGE : 2/4 TITLE : allocmem VS. malloc to request more far heap memory using farmalloc at this point, the block your program resides in cannot be resized. Due to this you will get a NULL back from the farmalloc call. --------------- 640K -------------- | DOS Free | | DOS Free | | Memory | | Memory | | | -------------- | | | allocmem() | | | | block | --------------- -------------| | Far Heap | | Far Heap | \ | ............| |............| | | TC++ | | TC++ | |- This block can no longer | Program | | Program | | be expanded on farmalloc | | | | / calls resulting in NULL --------------- -------------- pointers. | DOS | | DOS | | | | | --------------- -------------- Before allocmem() After allocmem() Note that anything performing a DOS allocation will have the same effect on your Turbo C++ program. This includes the loading of TSR programs. We can now see that this will only be fatal to programs requesting memory from the far heap. Therefore, allocations using malloc coming off of the near heap will not be affected. In addition we can see that if there were some way to reverse DOS's allocation scheme so that it would grab memory from the top down, that our farmalloc's could still work. It turns out that DOS interrupt 21h function 58h does just that. By issuing: _AX = 0x5801; _BX = 2; /* selected last fit allocation */ geninterrupt(0x21); DOS will then grab blocks in a top down fashion. ALWAYS return DOS to a first fit selection following the call to allocmem by loading up bx with 0. PRODUCT : Borland C++ NUMBER : 1008 VERSION : 3.0 OS : DOS DATE : October 19, 1993 PAGE : 3/4 TITLE : allocmem VS. malloc _AX = 0x5801; _BX = 0; /* select first fit allocation */ geninterrupt(0x21); Follows are two program which illustrate the problem and the work around. Program #1 shows conflict in memory allocation schemes: #include #include #include main() { unsigned seg, count = 0; char far *ptr; allocmem( 100, &seg ); /* allocates next available block */ printf(" Allocated block at %X:0000\n", seg); while ((ptr = farmalloc(50)) != NULL) count++; printf(" Allocated %u 50 byte pieces\n", count); /* can't allocate! */ return 0; } Program #2 offers resolutions: #include #include #include main() { unsigned seg, count = 0; char far *ptr; _AX = 0x5801; _BX = 2; geninterrupt(0x21); /* set allocation strategy to last fit */ allocmem( 100, &seg ); /* grab highest block */ _AX = 0x5801; _BX = 0; PRODUCT : Borland C++ NUMBER : 1008 VERSION : 3.0 OS : DOS DATE : October 19, 1993 PAGE : 4/4 TITLE : allocmem VS. malloc geninterrupt(0x21); /* reset allocation strategy */ printf(" Allocated block at %X:0000\n", seg); while ((ptr = farmalloc(50)) != NULL) count++; printf(" Allocated %u 50 byte pieces\n", count); return 0; } 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.