Index: vim-7.4.580.hg.6506/src/eval.c =================================================================== --- vim-7.4.580.hg.6506.orig/src/eval.c +++ vim-7.4.580.hg.6506/src/eval.c @@ -6927,48 +6927,51 @@ garbage_collect() free_unref_items(copyID) int copyID; { - dict_T *dd; - list_T *ll; + dict_T *dd, *dd_next; + list_T *ll, *ll_next; int did_free = FALSE; /* * Go through the list of dicts and free items without the copyID. */ - for (dd = first_dict; dd != NULL; ) + for (dd = first_dict; dd != NULL; ) { if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)) { /* Free the Dictionary and ordinary items it contains, but don't * recurse into Lists and Dictionaries, they will be in the list * of dicts or list of lists. */ + dd_next = dd->dv_used_next; dict_free(dd, FALSE); did_free = TRUE; - - /* restart, next dict may also have been freed */ - dd = first_dict; + dd = dd_next; } - else + else { dd = dd->dv_used_next; + } + } /* * Go through the list of lists and free items without the copyID. * But don't free a list that has a watcher (used in a for loop), these * are not referenced anywhere. */ - for (ll = first_list; ll != NULL; ) + for (ll = first_list; ll != NULL; ) { if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK) && ll->lv_watch == NULL) { /* Free the List and ordinary items it contains, but don't recurse * into Lists and Dictionaries, they will be in the list of dicts * or list of lists. */ + + ll_next = ll->lv_used_next; list_free(ll, FALSE); did_free = TRUE; - - /* restart, next list may also have been freed */ - ll = first_list; + ll = ll_next; } - else + else { ll = ll->lv_used_next; + } + } return did_free; } @@ -7125,6 +7128,7 @@ dict_free(d, recurse) /* Lock the hashtab, we don't want it to resize while freeing items. */ hash_lock(&d->dv_hashtab); + assert(d->dv_hashtab.ht_locked > 0); todo = (int)d->dv_hashtab.ht_used; for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) {