Home > Programmer's Guide > Advanced Issues

Garbage Collector

Each time an instance of an object is created with the New statement or the Clone statement, and each time a string is created, a new storage block is allocated in the heap. The size of the heap is strictly limited and programs would quickly run out of memory at runtime if the objects and the strings were not released after use.

In many languages, releasing the available memory resources is at the charge of the programmer, and is carried out with instructions usually called free or delete. With HB++, such instructions do not exist. The runtime library linked to your program, includes a routine called garbage collector whose role is to detect all the unused storage blocks automatically in order to release them.

Calling the garbage collector

To be effective, the garbage collector must run at regular intervals. If it does not run often enough, the memory is likely to become full of unused objects. If it runs too often, the percentage of CPU time devoted to the garbage collector becomes significant, and performance will drop.

The HB++ runtime library adopts a compromise which consists of starting the garbage collector every 64 allocations in the heap. Moreover, three particular circumstances cause it to run before this :

In most of your programs, you won't need to call MemCompact explicitly.

Garbage collector internals

The runtime library maintains a linked list of all the allocated storage blocks. Each storage block also contains some fields that are not accessible to the programmer in which information such as the type of the object stored in the block is maintained.

The execution of the garbage collector occurs in 5 steps.

The garbage collector can determine if a memory address in your program corresponds to a variable of type Long, String, Variant, or object, by using information generated by the compiler and information present in the management field of each memory block.

This explains why it is sometimes preferable to regularly call the garbage collector, rather than let it run only when the memory is saturated: step 4, which is recursive, can require many cycles if there are many objects.

Finally, one also understands why it is necessary to store the result of the function AddressOf in a variable of the type Long, even if the address returned is lower than 255 or 32767: variables of types Byte or Integer are not tested by the garbage collector, and the object could be released prematurely.

By rule of thumb, the execution of the garbage collector is about 10 milliseconds when only a few objects are released. This can increase to a few seconds when there are several hundred objects to examine.