solving some memory leaks in convexhull app. with a quite complex pointer/create/dealloc structure,
i finally created a global heap:seq[pointer] that 'contains' most create() in module, particularly the new***() procs:
proc newFace():ptr Face=
result=create(Face)
result.mark=VISIBLE
heap_add(result) # here pointer is added to 'heap' global var
at main object destructor i call heap_free (code attached), solution works fine with no more leaks at all,
i was wondering if nim provides a more elegant/idiomatic way to solve this kind of situations with many disperse fragmented memory chunks, something like:
let heap_mark = GC_heap_mark() # this provides a known point for all further 'create()' CG_heap_free(heap_mark) # dealloc all 'create()' from 'heap_mark'
heap depot mgr:
# heap depot
var heap : seq[pointer]
proc heap_init() = heap = @[]
proc heap_add(p:pointer) = heap.add(p)
proc heap_free()=
for p in heap: dealloc(p)
heap_init()
complete code: https://github.com/rforcen/nim/blob/main/convexhull/convexhull.nim
solving some memory leaks in convexhull app.
Sorry I have no idea what you are talking about -- maybe you have explained it on IRC, but I generally do not read IRC...
Did you had leaks with the default refc GC before? From my understanding with that one all should just work. Indeed the half edge structure is not easy, I had some problems to get it compile with ARC. I added a cursor annotation as the compiler told me, and my feeling is that it works with that now, see
https://github.com/StefanSalewski/cdt/blob/master/src/cdt/types.nim#L33
But I have not done a very carefully leak testing yet, was happy that I got it working at all that time. A more carefully investigation may follow, but maybe I will wait for Nim 2.0 to see if it works then at all. If not, I may have to use the dcel data structure instead.
are seq[ptr T] items deallocated when seq is destroyed?
No, they are not. A ptr is not an owner of data.
If performance is critical one may consider using memory pools, which allow faster allocations when all objects have the same size. Mratsim knows the details.
Note that your suggested seq[ptr T] may basically work, as the destructor can free the whole seq. But how would you do a dynamic app, that continuesly allocates and frees edges and faces?
If performance is critical one may consider using memory pools, which allow faster allocations when all objects have the same size. Mratsim knows the details.
Simple stack-based memory pool when dealloc happens in reverse order of alloc:
Full-blown thread-safe memory pool: