type
Data = tuple[x, y: int, s: string]
# allocate memory for Data on the heap:
var d = cast[ptr Data](alloc0(sizeof(Data)))
# create a new string on the garbage collected heap:
d.s = "abc"
# tell the GC that the string is not needed anymore:
GCunref(d.s)
# free the memory:
dealloc(d)
But when I test the code, I found that even if I've commented GCunref(d.s) out, no memory leak will happen (according to memory usage by top). Below is my full test code:
proc foobar(i:int) =
type
Data = tuple[x, y: int, s: string]
# allocate memory for Data on the heap:
var d = cast[ptr Data](alloc0(sizeof(Data)))
# create a new string on the garbage collected heap:
# use a different string everytime to prevent any "cache" if possible
d.s = $i
# tell the GC that the string is not needed anymore:
#GCunref(d.s)
# free the memory:
dealloc(d)
for i in 0..1000000000:
foobar(i)
I've tried to find out what happend by looking at definations of functions like unsureAsgnRef etc. in the source code, but they all give me the impression that memory leak should happen here. Have I got something wrong? Or GCunref() isn't necessary in this case?
Thanks. But I'm still under the impression that d.s = "abc" increases the ref count of "abc". If I understand correctly d.s = "abc" will lead to the execution of the following function:
proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerProc.} =
# unsureAsgnRef updates the reference counters only if dest is not on the
# stack. It is used by the code generator if it cannot decide wether a
# reference is in the stack or not (this can happen for var parameters).
if not isOnStack(dest):
if src != nil: incRef(usrToCell(src))
# XXX finally use assembler for the stack checking instead!
# the test for '!= nil' is correct, but I got tired of the segfaults
# resulting from the crappy stack checking:
if cast[int](dest[]) >=% PageSize: decRef(usrToCell(dest[]))
else:
# can't be an interior pointer if it's a stack location!
gcAssert(interiorAllocatedPtr(gch.region, dest) == nil,
"stack loc AND interior pointer")
dest[] = src
dest not on stack and src is not nil, so ref is increased?
dest not on stack and src is not nil, so ref is increased?
Hmm, that's a good point. I need to think about this.
Is it legal to continue to use x?
Yes.