diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-08-11 22:51:05 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-08-11 22:51:05 +0200 |
commit | c257487035f83aabe1c7e07f0552309e98f1bcb1 (patch) | |
tree | a2ab08ae7d067a1c5eba06a677f8480c5a166f6b /src/userfunc.c | |
parent | 91c5262b19fd2e558fe87b78c7767c7c5a270be8 (diff) | |
download | vim-git-c257487035f83aabe1c7e07f0552309e98f1bcb1.tar.gz |
patch 7.4.2197v7.4.2197
Problem: All functions are freed on exit, which may hide leaks.
Solution: Only free named functions, not reference counted ones.
Diffstat (limited to 'src/userfunc.c')
-rw-r--r-- | src/userfunc.c | 55 |
1 files changed, 36 insertions, 19 deletions
diff --git a/src/userfunc.c b/src/userfunc.c index 065425965..55bd97c5b 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -1099,22 +1099,53 @@ func_free(ufunc_T *fp, int force) vim_free(fp); } +/* + * There are two kinds of function names: + * 1. ordinary names, function defined with :function + * 2. numbered functions and lambdas + * For the first we only count the name stored in func_hashtab as a reference, + * using function() does not count as a reference, because the function is + * looked up by name. + */ + static int +func_name_refcount(char_u *name) +{ + return isdigit(*name) || *name == '<'; +} + #if defined(EXITFREE) || defined(PROTO) void free_all_functions(void) { hashitem_T *hi; + ufunc_T *fp; + long_u skipped = 0; + long_u todo; /* Need to start all over every time, because func_free() may change the * hash table. */ - while (func_hashtab.ht_used > 0) - for (hi = func_hashtab.ht_array; ; ++hi) + while (func_hashtab.ht_used > skipped) + { + todo = func_hashtab.ht_used; + for (hi = func_hashtab.ht_array; todo > 0; ++hi) if (!HASHITEM_EMPTY(hi)) { - func_free(HI2UF(hi), TRUE); - break; + --todo; + /* Only free functions that are not refcounted, those are + * supposed to be freed when no longer referenced. */ + fp = HI2UF(hi); + if (func_name_refcount(fp->uf_name)) + ++skipped; + else + { + func_free(fp, TRUE); + skipped = 0; + break; + } } - hash_clear(&func_hashtab); + } + if (skipped == 0) + hash_clear(&func_hashtab); } #endif @@ -1669,20 +1700,6 @@ theend: } /* - * There are two kinds of function names: - * 1. ordinary names, function defined with :function - * 2. numbered functions and lambdas - * For the first we only count the name stored in func_hashtab as a reference, - * using function() does not count as a reference, because the function is - * looked up by name. - */ - static int -func_name_refcount(char_u *name) -{ - return isdigit(*name) || *name == '<'; -} - -/* * ":function" */ void |