summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-01-23 23:00:30 +0100
committerBram Moolenaar <Bram@vim.org>2019-01-23 23:00:30 +0100
commit4456ab527a6a5faae9287f3bd2e52cc18966cfb0 (patch)
tree4b780e00f74b4b12aa61a18beb093908a3264543
parentcfc15237ab88ecb78b12030f6e04b87618b56124 (diff)
downloadvim-git-4456ab527a6a5faae9287f3bd2e52cc18966cfb0.tar.gz
patch 8.1.0800: may use a lot of memory when a function refers itselfv8.1.0800
Problem: May use a lot of memory when a function creates a cyclic reference. Solution: After saving a funccal many times, invoke the garbage collector. (closes #3835)
-rw-r--r--src/userfunc.c13
-rw-r--r--src/version.c2
2 files changed, 15 insertions, 0 deletions
diff --git a/src/userfunc.c b/src/userfunc.c
index 6887c2c5c..66e07b1f4 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -651,6 +651,7 @@ cleanup_function_call(funccall_T *fc)
listitem_T *li;
int todo;
dictitem_T *v;
+ static int made_copy = 0;
/* "fc" is still in use. This can happen when returning "a:000",
* assigning "l:" to a global variable or defining a closure.
@@ -673,6 +674,16 @@ cleanup_function_call(funccall_T *fc)
/* Make a copy of the a:000 items, since we didn't do that above. */
for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next)
copy_tv(&li->li_tv, &li->li_tv);
+
+ if (++made_copy == 10000)
+ {
+ // We have made a lot of copies. This can happen when
+ // repetitively calling a function that creates a reference to
+ // itself somehow. Call the garbage collector here to avoid using
+ // too much memory.
+ made_copy = 0;
+ (void)garbage_collect(FALSE);
+ }
}
}
@@ -723,6 +734,8 @@ call_user_func(
line_breakcheck(); /* check for CTRL-C hit */
fc = (funccall_T *)alloc(sizeof(funccall_T));
+ if (fc == NULL)
+ return;
fc->caller = current_funccal;
current_funccal = fc;
fc->func = fp;
diff --git a/src/version.c b/src/version.c
index d5ea08645..b8b06307d 100644
--- a/src/version.c
+++ b/src/version.c
@@ -792,6 +792,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 800,
+/**/
799,
/**/
798,