Hi,
I'm using Nim to build plugins for a C++ host app, loaded dynamically with dlopen(). I'm getting issues with the garbage collector and module level variables where the variables are getting corrupted. I think this simplified sample shows the issue, the sample crashes on about the fourth iteration. The GC_fullCollect in the CR_STEP case is just there for this sample to ensure the collection kicks in. I'm using the default GC.
var moduleSeq:seq[int]
type
cr_op* = enum
CR_LOAD = 0, CR_STEP = 1, CR_UNLOAD = 2, CR_CLOSE = 3,
# Function prototype
{.emit: """
void NimMain(void);
""".}
proc cr_main(ctx: pointer, operation: cr_op): cint {.cdecl, exportc, dynlib.} =
var a {.volatile.}: int
case operation:
of CR_LOAD:
{.emit: """
NimMain();
""".}
of CR_STEP:
nimGC_setStackBottom(cast[pointer](cast[uint](addr a)))
moduleSeq.add(0)
GC_fullCollect()
of CR_UNLOAD, CR_CLOSE:
GC_fullCollect()
result = 1
The host app calls the shared lib cr_main proc initially with CR_LOAD and then every tick with CR_STEP. Calling NimMain makes no apparent difference. Setting the stack bottom makes the GC work correctly with local variables.
Any obvious errors, ideas how I can get this to work or alterative approaches?
Thanks. That does stop the crash.
I previously tried arc in the real code and it seemed to leak, according to GC_getStatistics "occupied memory" at least, unless I altered the module seq at the outer level of the proc (ie. outside of any conditional checks). I'll try and get together a sample that demonstrates that.
What is the recommended default GC? This is for a game so needs to complete in a bounded time. As planned there will be many shared libraries, so each library is typically fairly small and only uses the GC for working variables, all the persistent data is handled by the C++ framework.
--gc:arc|orc are on the way to become the default choice for memory management. ORC is just ARC with a cycle collector (so you don't need it when you don't have cycles)
Also for leaks you should compile your program like --gc:arc -d:useMalloc and then run it with valgrind like valgrind --leak-check=full ./program. This might not be needed anymore with https://github.com/nim-lang/Nim/pull/14467 though
or at least 1.2.2 beta release which has most ARC fixes backported from devel
There's a newer 1.2.2-beta with even more bugfixes: https://github.com/nim-lang/nightlies/releases/tag/2020-06-01-version-1-2-5702a60