-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Summary
This came about when working with dynamic libraries. If you write a dynamic library in Nim and then load it into a separate program there is no (documented) way to free all the memory if the loader program unloads the dynamic library. This means that if a system loads and unloads a dynamic library it will keep increasing in memory.
Description
What I propose is to create a procedure NimQuit opposite of NimMain which will destroy all memory. Calling any other code using GC after that will be undefined behaviour. This would then be called automatically in .fini by attaching __attribute((destructor))__ or hooking in DllMain, similar to how NimMain is called today. And analogous to how --noMain disables this behaviour --noQuit should prevent it from being called and NimQuit must be called exlicitly.
Alternatives
No response
Examples
As a simple example/testing ground I wrote this:
loader.nim:
import std/dynlib
type
InitFunction = proc () {.cdecl.}
DeinitFunction = proc () {.cdecl.}
proc loadDynamic() =
let lib = loadLib("./liblibrary.so")
assert lib != nil, "Error loading library"
let init = cast[InitFunction](lib.symAddr("dynlib_init"))
assert init != nil, "Error loading 'init' function from library"
let deinit = cast[DeinitFunction](lib.symAddr("dynlib_deinit"))
assert deinit != nil, "Error loading 'deinit' function from library"
init()
deinit()
unloadLib(lib)
while true:
loadDynamic()library.nim:
var x = newSeq[byte](uint16.high)
proc NimMain() {.cdecl, importc.}
proc dynlib_init() {.cdecl, exportc, dynlib.} =
NimMain()
echo "Loaded dynamic library"
proc dynlib_deinit() {.cdecl, exportc, dynlib.} =
GC_FullCollect()Compiled with:
nim c --gc:orc loader.nim
and
nim c --app:lib --noMain --gc:orc library.nim
Backwards Compatibility
No response
Links
No response