next up previous contents
Next: using DOS memory under Up: Memory issues Previous: The stack

The heap

  The heap is used to store all dynamic variables, and to store class instances. The interface to the heap is the same as in Turbo Pascal, although the effects are maybe not the same. On top of that, the Free Pascal run-time library has some extra possibilities, not available in Turbo Pascal. These extra possibilities are explained in the next subsections.

The heap grows

Free Pascal supports the HeapEerror procedural variable. If this variable is non-nil, then it is called in case you try to allocate memory, and the heap is full. By default, HeapError points to the GrowHeap function, which tries to increase the heap.

The growheap function issues a system call to try to increase the size of the memory available to your program. It first tries to increase memory in a 1 Mb. chunk. If this fails, it tries to increase the heap by the amount you requested from the heap.

If the call to GrowHeap has failed, then a run-time error is generated, or nil is returned, depending on the GrowHeap result.

If the call to GrowHeap was successful, then the needed memory will be allocated.

Using Blocks

If you need to allocate a lot of small block for a small period, then you may want to recompile the run-time library with the USEBLOCKS symbol defined. If it is recompiled, then the heap management is done in a different way.

The run-time library keeps a linked list of allocated blocks with size up to 256 bytesgif. By default, it keeps 32 of these listsgif.

When a piece of memory in a block is deallocated, the heap manager doesn't really deallocate the occupied memory. The block is simply put in the linked list corresponding to its size.

When you then again request a block of memory, the manager checks in the list if there is a non-allocated block which fits the size you need (rounded to 8 bytes). If so, the block is used to allocate the memory you requested.

This method of allocating works faster if the heap is very fragmented, and you allocate a lot of small memory chunks.

Since it is invisible to the program, this provides an easy way of improving the performance of the heap manager.

Using the split heap

Remark : The split heap is still somewhat buggy. Use at your own risk for the moment.

The split heap can be used to quickly release a lot of blocks you alloated previously.

Suppose that in a part of your program, you allocate a lot of memory chunks on the heap. Suppose that you know that you'll release all this memory when this particular part of you program is finished.

In Turbo Pascal, you could foresee this, and mark the position of the heap (using the Mark function) when entering this particular part of your program, and release the occupied memory in one call with the Release call.

For most purposes, this works very good. But sometimes, you may need to allocate something on the heap that you don't want deallocated when you release the allocated memory. That is where the split heap comes in.

When you split the heap, the heap manager keeps 2 heaps: the base heap (the normal heap), and the temporary heap. After the call to split the heap, memory is allocated from the temporary heap. When you're finished using all this memory, you unsplit the heap. This clears all the memory on the split heap with one call. After that, memory will be allocated from the base heap again.

So far, nothing special, nothing that can't be done with calls to mark and release. Suppose now that you have split the heap, and that you've come to a point where you need to allocate memory that is to stay allocated after you unsplit the heap again. At this point, mark and release are of no use. But when using the split heap, you can tell the heap manager to -temporarily- use the base heap again to allocate memory. When you've allocated the needed memory, you can tell the heap manager that it should start using the temporary heap again. When you're finished using the temporary heap, you release it, and the memory you allocated on the base heap will still be allocated.

To use the split-heap, you must recompile the run-time library with the TempHeap symbol defined. This means that the following functions are available :

  procedure Split_Heap;
  procedure Switch_To_Base_Heap;
  procedure Switch_To_Temp_Heap;
  procedure Switch_Heap;
  procedure ReleaseTempHeap;
  procedure GetempMem(var p : pointer;size : longint);
split_heap is used to split the heap. It cannot be called two times in a row, without a call to releasetempheap. Releasetempheap completely releases the memory used by the temporary heap. Switching temporarily back to the base heap can be done using the switch_to_base_heap call, and returning to the temporary heap is done using the switch_to_temp_heap call. Switching from one to the other without knowing on which one your are right now, can be done using the switch_heap call, which will split the heap first if needed.

A call to GetTempMem will allocate a memory block on the temporary heap, whatever the current heap is. The current heap after this call will be the temporary heap.

Typically, what will appear in your code is the following sequence :

Split_Heap
...
{ Memory allocation }
...
{ !! non-volatile memory needed !!}
Switch_To_Base_Heap;
getmem (P,size);
Switch_To_Temp_Heap;
...
{Memory allocation}
...
ReleaseTempHeap;
{All allocated memory is now freed, except for the memory pointed to by 'P' }
...


next up previous contents
Next: using DOS memory under Up: Memory issues Previous: The stack

Michael Van Canneyt
Thu Sep 10 14:04:11 CEST 1998