forked from aniani/vim
patch 7.4.2197
Problem: All functions are freed on exit, which may hide leaks. Solution: Only free named functions, not reference counted ones.
This commit is contained in:
@@ -1099,21 +1099,52 @@ func_free(ufunc_T *fp, int force)
|
|||||||
vim_free(fp);
|
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)
|
#if defined(EXITFREE) || defined(PROTO)
|
||||||
void
|
void
|
||||||
free_all_functions(void)
|
free_all_functions(void)
|
||||||
{
|
{
|
||||||
hashitem_T *hi;
|
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
|
/* Need to start all over every time, because func_free() may change the
|
||||||
* hash table. */
|
* hash table. */
|
||||||
while (func_hashtab.ht_used > 0)
|
while (func_hashtab.ht_used > skipped)
|
||||||
for (hi = func_hashtab.ht_array; ; ++hi)
|
{
|
||||||
|
todo = func_hashtab.ht_used;
|
||||||
|
for (hi = func_hashtab.ht_array; todo > 0; ++hi)
|
||||||
if (!HASHITEM_EMPTY(hi))
|
if (!HASHITEM_EMPTY(hi))
|
||||||
{
|
{
|
||||||
func_free(HI2UF(hi), TRUE);
|
--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;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (skipped == 0)
|
||||||
hash_clear(&func_hashtab);
|
hash_clear(&func_hashtab);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1668,20 +1699,6 @@ theend:
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 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"
|
* ":function"
|
||||||
*/
|
*/
|
||||||
|
@@ -763,6 +763,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2197,
|
||||||
/**/
|
/**/
|
||||||
2196,
|
2196,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user