HALCON: Memory management in .NET

Writing applications in .NET languages, e.g. C#, is quite popular and one benefit is of course that the programmer does not need to worry about memory management. .NET provides a convenient dynamic memory management. Unreferenced objects are removed automatically by the garbage collector (GC). Of course, HALCON/.NET makes use of this concept.

.NET variables
.NET data types can be classified according to whether a variable of a particular type stores its own data or a pointer to the data. If it stores its own data, it is a value type; if it holds a pointer to data elsewhere in memory, it is a reference type. Value types are numerical types like int or double and structs, while strings and all classes are reference types.

The most important thing to keep in mind for all classes from the HALCON/.NET interface is: HALCON Variables in .NET are only references to data.

This means that reference types do not contain the actual data stored in a variable, but they contain a reference to the variables. In other words, they refer to a memory location. Furthermore, referenced data is never overwritten by assignments. When a variable is assigned a new value, the old data is de-referenced and memory is allocated for the new data.

Garbage Collector
The garbage collector tidies up data that is not referenced any more – either because the variable leaves its scope or it is not referenced by any part of the code anymore. The garbage collector becomes active when the estimated size of allocated memory exceeds a certain threshold.

In the context of HALCON one should note that the garbage collector only recognizes the object structure to which the variable points plus the managed data. Managed data is referenced in HTuple, whereas HObject contains unmanaged data which is not recognized by the garbage collector. HALCON’s iconic variables (images, regions,…) seem to be rather “small” for the garbage collector, because they only contain a reference to the (in many cases rather large) iconic objects in the database. Thus, the garbage collector may not free such variables even if they are not used anymore.

Especially in loops, this causes .NET to repeatedly allocate memory for the new instantiation of images, as the data is not overwritten. The garbage collector in turn does not see the constant increase of required memory. In some cases memory consumption grows such that one may observe error 6001 (not enough memory) for no obvious reason.

To release this memory, the garbage collector can become active nevertheless by calling it explicitly:

GC.Collect();
GC.WaitForPendingFinalizers();

A good point for calling the garbage collector would be at the end of the main processing loop. This makes sure that your .NET application releases memory regularly in each cycle.

The manual disposal of individual objects is also possible by calling the method Dispose. The Dispose method is especially useful in small loops, where the direct call of the garbage collector is too expensive.

Need any further help? Contact support at Multipix