<aside> 🌐 https://ghostscript.com/r/Ghostscript-Memory-Management-Overview
</aside>
Ghostscript/GhostPDL memory management is based around what we term “allocators”. Those are built around the gs_memory_t object.
Heap Allocator
Starting at the “lowest” level, we have the “heap allocator” (base/gsmalloc.c). The heap allocator is slightly special in that there should only be one instance
Multiple Allocator Instances
As is possibly implied by the description, the chunk allocator can have several instances in existence at a given time.
Although not restricted to the garbage collector, struct descriptors can also, optionally include a “finalize” method, which the memory manager will call when instances of that
An important point to note about the garbage collector: an clump allocator with the garbager attached can effectly request that the garbage collector be run. But it is up to the Postscript interpreter to actually initiate garbage collection.
Reference Counting
Ghostscript also makes of reference counting. Reference counted objects have a ‘substructure’ (named ‘rc’) embedded in them containing the reference count itself, plus the memory allocator used in the creation of the object.
It is extremely important to realise that any allocator can be used to create a reference counted object: non-garbage collected, garbage collected, stable or non-stable.
All but the first of those is, frankly, counter-intuitive, since neither the garbage collector, nor the Postscript save/restore mechanism take any account of the reference count of an object. Thus, if the object was created in Postscript memory, it can be freed by a restore even if the reference count is greater than 0. Also, if it was allocated in garbage collected memory, and reaches a point where no other objects in garbage collected memory reference it, the object can be freed by the garbage collector even if the reference count is greater than 0.
It is best practice to avoid adding new reference counted objects allocated in anything other than a non-garbage collected allocated, if possible.
Identifying Which Allocator Was Used To Create An Object
Conventionally, non-trivial, long lived objects/structures in Ghostscript contain a pointer to the allocator use to allocate them. This will be a gs_memory_t
pointer called either ‘memory’ or ‘mem’ - in the case of reference counted objects, in the ‘rc’ substructure, and called ‘memory’. The gs_memory_t
structure contains several pointers:
stable_memory
procs
gs_lib_ctx
non_gc_memory
thread_safe_memory