patch 8.2.1819: Vim9: Memory leak when using a closure
Problem: Vim9: Memory leak when using a closure.
Solution: Compute the mininal refcount in the funcstack. Reenable disabled
tests.
diff --git a/src/eval.c b/src/eval.c
index f7657b4..98d16c8 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3984,21 +3984,12 @@
else
func_ptr_unref(pt->pt_func);
+ // Decrease the reference count for the context of a closure. If down
+ // to the minimum it may be time to free it.
if (pt->pt_funcstack != NULL)
{
- // Decrease the reference count for the context of a closure. If down
- // to zero free it and clear the variables on the stack.
- if (--pt->pt_funcstack->fs_refcount == 0)
- {
- garray_T *gap = &pt->pt_funcstack->fs_ga;
- typval_T *stack = gap->ga_data;
-
- for (i = 0; i < gap->ga_len; ++i)
- clear_tv(stack + i);
- ga_clear(gap);
- vim_free(pt->pt_funcstack);
- }
- pt->pt_funcstack = NULL;
+ --pt->pt_funcstack->fs_refcount;
+ funcstack_check_refcount(pt->pt_funcstack);
}
vim_free(pt);
@@ -4011,8 +4002,16 @@
void
partial_unref(partial_T *pt)
{
- if (pt != NULL && --pt->pt_refcount <= 0)
- partial_free(pt);
+ if (pt != NULL)
+ {
+ if (--pt->pt_refcount <= 0)
+ partial_free(pt);
+
+ // If the reference count goes down to one, the funcstack may be the
+ // only reference and can be freed if no other partials reference it.
+ else if (pt->pt_refcount == 1 && pt->pt_funcstack != NULL)
+ funcstack_check_refcount(pt->pt_funcstack);
+ }
}
/*