Mercurial > vim
comparison src/userfunc.c @ 22326:fb69b43d73f3 v8.2.1712
patch 8.2.1712: Vim9: leaking memory when calling a lambda
Commit: https://github.com/vim/vim/commit/a05e524f3aa8eadc2dbd0ad8ff6db9407ac7ac7e
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Sep 19 18:19:19 2020 +0200
patch 8.2.1712: Vim9: leaking memory when calling a lambda
Problem: Vim9: leaking memory when calling a lambda.
Solution: Decrement function reference from ISN_DCALL.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 19 Sep 2020 18:30:04 +0200 |
parents | a4ed0de125d9 |
children | 56f674e7518c |
comparison
equal
deleted
inserted
replaced
22325:543812d79fae | 22326:fb69b43d73f3 |
---|---|
1056 * 2. numbered functions and lambdas | 1056 * 2. numbered functions and lambdas |
1057 * For the first we only count the name stored in func_hashtab as a reference, | 1057 * For the first we only count the name stored in func_hashtab as a reference, |
1058 * using function() does not count as a reference, because the function is | 1058 * using function() does not count as a reference, because the function is |
1059 * looked up by name. | 1059 * looked up by name. |
1060 */ | 1060 */ |
1061 static int | 1061 int |
1062 func_name_refcount(char_u *name) | 1062 func_name_refcount(char_u *name) |
1063 { | 1063 { |
1064 return isdigit(*name) || *name == '<'; | 1064 return isdigit(*name) || *name == '<'; |
1065 } | 1065 } |
1066 | 1066 |
1174 | 1174 |
1175 /* | 1175 /* |
1176 * Free a function and remove it from the list of functions. Does not free | 1176 * Free a function and remove it from the list of functions. Does not free |
1177 * what a function contains, call func_clear() first. | 1177 * what a function contains, call func_clear() first. |
1178 * When "force" is TRUE we are exiting. | 1178 * When "force" is TRUE we are exiting. |
1179 */ | 1179 * Returns OK when the function was actually freed. |
1180 static void | 1180 */ |
1181 static int | |
1181 func_free(ufunc_T *fp, int force) | 1182 func_free(ufunc_T *fp, int force) |
1182 { | 1183 { |
1183 // Only remove it when not done already, otherwise we would remove a newer | 1184 // Only remove it when not done already, otherwise we would remove a newer |
1184 // version of the function with the same name. | 1185 // version of the function with the same name. |
1185 if ((fp->uf_flags & (FC_DELETED | FC_REMOVED)) == 0) | 1186 if ((fp->uf_flags & (FC_DELETED | FC_REMOVED)) == 0) |
1189 { | 1190 { |
1190 if (fp->uf_dfunc_idx > 0) | 1191 if (fp->uf_dfunc_idx > 0) |
1191 unlink_def_function(fp); | 1192 unlink_def_function(fp); |
1192 VIM_CLEAR(fp->uf_name_exp); | 1193 VIM_CLEAR(fp->uf_name_exp); |
1193 vim_free(fp); | 1194 vim_free(fp); |
1194 } | 1195 return OK; |
1196 } | |
1197 return FAIL; | |
1195 } | 1198 } |
1196 | 1199 |
1197 /* | 1200 /* |
1198 * Free all things that a function contains and free the function itself. | 1201 * Free all things that a function contains and free the function itself. |
1199 * When "force" is TRUE we are exiting. | 1202 * When "force" is TRUE we are exiting. |
1888 fp = HI2UF(hi); | 1891 fp = HI2UF(hi); |
1889 if (func_name_refcount(fp->uf_name)) | 1892 if (func_name_refcount(fp->uf_name)) |
1890 ++skipped; | 1893 ++skipped; |
1891 else | 1894 else |
1892 { | 1895 { |
1893 func_free(fp, FALSE); | 1896 if (func_free(fp, FALSE) == OK) |
1894 skipped = 0; | 1897 { |
1895 break; | 1898 skipped = 0; |
1899 break; | |
1900 } | |
1901 // did not actually free it | |
1902 ++skipped; | |
1896 } | 1903 } |
1897 } | 1904 } |
1898 } | 1905 } |
1899 if (skipped == 0) | 1906 if (skipped == 0) |
1900 hash_clear(&func_hashtab); | 1907 hash_clear(&func_hashtab); |