On Sun, Mar 30, 2008 at 2:17 PM, Bram Moolenaar <[EMAIL PROTECTED]> wrote:

>  Andy Wokula wrote:
>
>  > Strange bug and crash with :echo and lists,
>  > observed on gVim 7.1.283 (also gVim 7.0):
>  >
>  >
>  > let list = []
>  > call add(list, "abc")
>  > call add(list, "def")
>  > echo list[0]
>  > " ^ important
>  > let list = reverse(list)
>  > call add(list, "ghi")
>  > let left = list[: 1]
>  > let right = []
>  >
>  > " echo list[0] list[1] list[2]
>  > " " ^ crash, when uncommented!
>  >
>  > echo left list[2] right
>  > " ['abc', 'ghi'] ghi []           wrong
>  >
>  > let left = list[: 1]
>  >
>  > echo left list[2] right
>  > " ['def', 'abc'] ghi []           ok
>
>  I can reproduce it.  Also when it's shorter:
>
>  let list = []
>  call add(list, "abc")
>  call add(list, "def")
>  echo list[0]
>  let list = reverse(list)
>  call add(list, "ghi")
>  echo list[0] list[1] list[2]
>
>  I suspect the reference counter is wrong somewhere, possibly for the
>  first "echo" line.


I found the root cause of that bug.  The list contains a
cache (index in list + value) and that cache should be
invalidated when doing some operations on the list
such as:
- sorting the list
- inserting element in list
- removing element from list.

Also, when reversing the list, the cache index needed
to be updated.

Appending to the list does not need to invalidate cache.

Attached patch fixes all this.

Possible improvement: inserting or deleting element from
the list could get away with not invalidating the cache when
cached entry is before inserted/deleted element.  But it's
simpler and less risky to invalidate cache unconditionally
I think.

Cheers
-- Dominique

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Index: eval.c
===================================================================
RCS file: /cvsroot/vim/vim7/src/eval.c,v
retrieving revision 1.248
diff -c -r1.248 eval.c
*** eval.c	20 Mar 2008 12:23:49 -0000	1.248
--- eval.c	30 Mar 2008 17:14:26 -0000
***************
*** 5890,5895 ****
--- 5890,5896 ----
  	}
  	item->li_prev = ni;
  	++l->lv_len;
+ 	l->lv_idx_item = NULL; /* invalidate cache */
      }
      return OK;
  }
***************
*** 13652,13657 ****
--- 13653,13659 ----
  			    l->lv_last = item2;
  			    item->li_prev = NULL;
  			    item2->li_next = NULL;
+ 			    l->lv_idx_item = NULL; /* invalidate cache */
  			    l->lv_len = cnt;
  			}
  		    }
***************
*** 13955,13960 ****
--- 13957,13963 ----
  	rettv->v_type = VAR_LIST;
  	++l->lv_refcount;
      }
+     l->lv_idx = l->lv_len - l->lv_idx;
  }
  
  #define SP_NOMOVE	0x01	    /* don't move cursor */
***************
*** 15202,15208 ****
  	    if (!item_compare_func_err)
  	    {
  		/* Clear the List and append the items in the sorted order. */
! 		l->lv_first = l->lv_last = NULL;
  		l->lv_len = 0;
  		for (i = 0; i < len; ++i)
  		    list_append(l, ptrs[i]);
--- 15205,15211 ----
  	    if (!item_compare_func_err)
  	    {
  		/* Clear the List and append the items in the sorted order. */
! 		l->lv_first = l->lv_last = l->lv_idx_item = NULL;
  		l->lv_len = 0;
  		for (i = 0; i < len; ++i)
  		    list_append(l, ptrs[i]);

Raspunde prin e-mail lui