Re: Bug: E685, SEGV - a:000 garbage collected too early?
Bram Moolenaar skribis: Matt Wozniski wrote: function! ReturnArgs(...) return a:000 endfunction Seems to work fine? echo ReturnArgs(1, 2, 3) SEGV echo string(ReturnArgs(1, 2, 3)) function! MakeArgsDict(...) return { 'args': a:000 } endfunction E685 Internal Error echo MakeArgsDict(1, 2, 3) SEGV echo string(MakeArgsDict(1, 2, 3)) For it crashes a while after trying these things. Most likely the reference count for a:000 is wrong. Never thought of someone returning it... [...] I have made a patch to fix this. It's complicated stuff, I hope I thought of everything that could possibly go wrong, including memory leaks. Dominique, can you try including the patch and running valgrind? And check for memory leaks? It looks good to me. Patch fixes the bug and I can't see any error or leak with valgrind memory checker. I tried all test cases reported by Matt Wozniski, as well as make test (all tests passed). -- Dominique --~--~-~--~~~---~--~~ You received this message from the vim_dev maillist. For more information, visit http://www.vim.org/maillist.php -~--~~~~--~~--~--~---
Re: Bug: E685, SEGV - a:000 garbage collected too early?
Dominique Pelle wrote: Bram Moolenaar skribis: Matt Wozniski wrote: function! ReturnArgs(...) return a:000 endfunction Seems to work fine? echo ReturnArgs(1, 2, 3) SEGV echo string(ReturnArgs(1, 2, 3)) function! MakeArgsDict(...) return { 'args': a:000 } endfunction E685 Internal Error echo MakeArgsDict(1, 2, 3) SEGV echo string(MakeArgsDict(1, 2, 3)) For it crashes a while after trying these things. Most likely the reference count for a:000 is wrong. Never thought of someone returning it... [...] I have made a patch to fix this. It's complicated stuff, I hope I thought of everything that could possibly go wrong, including memory leaks. Dominique, can you try including the patch and running valgrind? And check for memory leaks? It looks good to me. Patch fixes the bug and I can't see any error or leak with valgrind memory checker. I tried all test cases reported by Matt Wozniski, as well as make test (all tests passed). Thanks for checking this. I'll have last look at it and send it out soon. -- ARTHUR: No, hang on! Just answer the five questions ... GALAHAD: Three questions ... ARTHUR: Three questions ... And we shall watch ... and pray. Monty Python and the Holy Grail PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- b...@moolenaar.net -- http://www.Moolenaar.net \\\ ///sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\download, build and distribute -- http://www.A-A-P.org/// \\\help me help AIDS victims -- http://ICCF-Holland.org/// --~--~-~--~~~---~--~~ You received this message from the vim_dev maillist. For more information, visit http://www.vim.org/maillist.php -~--~~~~--~~--~--~---
Re: Bug: E685, SEGV - a:000 garbage collected too early?
Dominique Pelle wrote: 2008/12/16 Bram Moolenaar b...@moolenaar.net: Matt Wozniski wrote: function! ReturnArgs(...) return a:000 endfunction Seems to work fine? echo ReturnArgs(1, 2, 3) SEGV echo string(ReturnArgs(1, 2, 3)) function! MakeArgsDict(...) return { 'args': a:000 } endfunction E685 Internal Error echo MakeArgsDict(1, 2, 3) SEGV echo string(MakeArgsDict(1, 2, 3)) For it crashes a while after trying these things. Most likely the reference count for a:000 is wrong. Never thought of someone returning it... When I debugged, I found that v_list was pointing to an invalid address, which had been set in call_user_func() to fc.l_varlist; This variable is in the stack and was only valid while in call_user_func() and the functions it may calls. Somehow, a list still refers to this address after returning from call_user_func() so v_list points then to an invalid address. Making variable fc static (in function call_user_func()) avoids using an invalid address and thus avoids a crash, but it's still not the right way to fix it. Seems to work fine? echo ReturnArgs(1, 2, 3) Actually, even though this appears to work, valgrind memory checker already sees a problem there: ==23275== Invalid read of size 4 ==23275==at 0x809C577: echo_string (eval.c:7232) ==23275==by 0x80AD48C: ex_echo (eval.c:19481) ==23275==by 0x80C71C6: do_one_cmd (ex_docmd.c:2622) ==23275==by 0x80C4A46: do_cmdline (ex_docmd.c:1096) ==23275==by 0x8149D7A: nv_colon (normal.c:5233) ==23275==by 0x81433FE: normal_cmd (normal.c:1200) ==23275==by 0x810678D: main_loop (main.c:1180) ==23275==by 0x81062DA: main (main.c:939) ==23275== Address 0xbef5e280 is not stack'd, malloc'd or (recently) free'd ==23275== ==23275== Invalid write of size 4 ==23275==at 0x809C59D: echo_string (eval.c:7239) ==23275==by 0x80AD48C: ex_echo (eval.c:19481) ==23275==by 0x80C71C6: do_one_cmd (ex_docmd.c:2622) ==23275==by 0x80C4A46: do_cmdline (ex_docmd.c:1096) ==23275==by 0x8149D7A: nv_colon (normal.c:5233) ==23275==by 0x81433FE: normal_cmd (normal.c:1200) ==23275==by 0x810678D: main_loop (main.c:1180) ==23275==by 0x81062DA: main (main.c:939) ==23275== Address 0xbef5e280 is not stack'd, malloc'd or (recently) free'd (etc, more errors to follow) Line eval.c:7232 is: 7232 else if (copyID != 0 tv-vval.v_list-lv_copyID == copyID) 7233 { 7234 *tofree = NULL; 7235 r = (char_u *)[...]; 7236 } 'tv-vval.v_list' points to the invalid address which set as there at line 21193: 21191 v-di_tv.v_type = VAR_LIST; 21192 v-di_tv.v_lock = VAR_FIXED; 21193 v-di_tv.vval.v_list = fc.l_varlist; (fc being a local var in the stack) What is happening here is that a few things are put on the stack to avoid malloc()/free() calls. These are quite expensive and adds overhead to every function call. The reference count of these are not used. When the function returns, the items automatically disappear. That's a bit of a problem if you return the value or assigned it to a global variable. I think the only proper solution is to do that malloc()/free(). Not only for a:000, but also for l: and a:. And all elements contained in them, that's going to be time consuming. Another method would be to disallow passing these dictionaries to outside the function scope. One would have to make a copy instead. Checking for this may be complicated though. And this also doesn't solve the problem for variables such as a:firstline that are also on the stack. It looks like the best solution is to put the whole funccall_T in allocated memory. And only free it when all the reference counts are back to zero. Need to make a list of them and add some code to the garbage collector. -- ARTHUR: But if he was dying, he wouldn't bother to carve Arrggghhh. He'd just say it. BROTHER MAYNARD: It's down there carved in stone. GALAHAD: Perhaps he was dictating. Monty Python and the Holy Grail PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- b...@moolenaar.net -- http://www.Moolenaar.net \\\ ///sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\download, build and distribute -- http://www.A-A-P.org/// \\\help me help AIDS victims -- http://ICCF-Holland.org/// --~--~-~--~~~---~--~~ You received this message from the vim_dev maillist. For more information, visit http://www.vim.org/maillist.php -~--~~~~--~~--~--~---
Re: Bug: E685, SEGV - a:000 garbage collected too early?
Tony Mechelynck wrote: On 17/12/08 13:34, Bram Moolenaar wrote: Dominique Pelle wrote: 2008/12/16 Bram Moolenaarb...@moolenaar.net: Matt Wozniski wrote: function! ReturnArgs(...) return a:000 endfunction Seems to work fine? echo ReturnArgs(1, 2, 3) SEGV echo string(ReturnArgs(1, 2, 3)) function! MakeArgsDict(...) return { 'args': a:000 } endfunction E685 Internal Error echo MakeArgsDict(1, 2, 3) SEGV echo string(MakeArgsDict(1, 2, 3)) For it crashes a while after trying these things. Most likely the reference count for a:000 is wrong. Never thought of someone returning it... When I debugged, I found that v_list was pointing to an invalid address, which had been set in call_user_func() tofc.l_varlist; This variable is in the stack and was only valid while in call_user_func() and the functions it may calls. Somehow, a list still refers to this address after returning from call_user_func() so v_list points then to an invalid address. Making variable fc static (in function call_user_func()) avoids using an invalid address and thus avoids a crash, but it's still not the right way to fix it. Seems to work fine? echo ReturnArgs(1, 2, 3) Actually, even though this appears to work, valgrind memory checker already sees a problem there: ==23275== Invalid read of size 4 ==23275==at 0x809C577: echo_string (eval.c:7232) ==23275==by 0x80AD48C: ex_echo (eval.c:19481) ==23275==by 0x80C71C6: do_one_cmd (ex_docmd.c:2622) ==23275==by 0x80C4A46: do_cmdline (ex_docmd.c:1096) ==23275==by 0x8149D7A: nv_colon (normal.c:5233) ==23275==by 0x81433FE: normal_cmd (normal.c:1200) ==23275==by 0x810678D: main_loop (main.c:1180) ==23275==by 0x81062DA: main (main.c:939) ==23275== Address 0xbef5e280 is not stack'd, malloc'd or (recently) free'd ==23275== ==23275== Invalid write of size 4 ==23275==at 0x809C59D: echo_string (eval.c:7239) ==23275==by 0x80AD48C: ex_echo (eval.c:19481) ==23275==by 0x80C71C6: do_one_cmd (ex_docmd.c:2622) ==23275==by 0x80C4A46: do_cmdline (ex_docmd.c:1096) ==23275==by 0x8149D7A: nv_colon (normal.c:5233) ==23275==by 0x81433FE: normal_cmd (normal.c:1200) ==23275==by 0x810678D: main_loop (main.c:1180) ==23275==by 0x81062DA: main (main.c:939) ==23275== Address 0xbef5e280 is not stack'd, malloc'd or (recently) free'd (etc, more errors to follow) Line eval.c:7232 is: 7232 else if (copyID != 0 tv-vval.v_list-lv_copyID == copyID) 7233 { 7234 *tofree = NULL; 7235 r = (char_u *)[...]; 7236 } 'tv-vval.v_list' points to the invalid address which set as there at line 21193: 21191 v-di_tv.v_type = VAR_LIST; 21192 v-di_tv.v_lock = VAR_FIXED; 21193 v-di_tv.vval.v_list =fc.l_varlist; (fc being a local var in the stack) What is happening here is that a few things are put on the stack to avoid malloc()/free() calls. These are quite expensive and adds overhead to every function call. The reference count of these are not used. When the function returns, the items automatically disappear. That's a bit of a problem if you return the value or assigned it to a global variable. I think the only proper solution is to do that malloc()/free(). Not only for a:000, but also for l: and a:. And all elements contained in them, that's going to be time consuming. Another method would be to disallow passing these dictionaries to outside the function scope. One would have to make a copy instead. Checking for this may be complicated though. And this also doesn't solve the problem for variables such as a:firstline that are also on the stack. It looks like the best solution is to put the whole funccall_T in allocated memory. And only free it when all the reference counts are back to zero. Need to make a list of them and add some code to the garbage collector. When returning a Number (e.g. :return a:lastline) or a Float, I suppose the return method guarantees that there'll be no problem. I'm less certain about returning a String variable local to the function, but I suppose existing code already provides for that. A Funcref to a function defined inside the function should remain valid -- or does it? But what we're talking about here is when the returned object is a List or Dictionary containing (at any level of depth) something local to the function, which would disappear at return-time. (Returning a pointer to a _global_ List or Dictionary ought to be no problem if no local elements or sub-elements have been added by the function.) This only matters for a:000, l: and a:. These are allocated on the stack. All other things are in allocated memory and can be passed around without problems. Proposed solution: returning a List or
Re: Bug: E685, SEGV - a:000 garbage collected too early?
Matt Wozniski wrote: function! ReturnArgs(...) return a:000 endfunction Seems to work fine? echo ReturnArgs(1, 2, 3) SEGV echo string(ReturnArgs(1, 2, 3)) function! MakeArgsDict(...) return { 'args': a:000 } endfunction E685 Internal Error echo MakeArgsDict(1, 2, 3) SEGV echo string(MakeArgsDict(1, 2, 3)) For it crashes a while after trying these things. Most likely the reference count for a:000 is wrong. Never thought of someone returning it... [...] I have made a patch to fix this. It's complicated stuff, I hope I thought of everything that could possibly go wrong, including memory leaks. Dominique, can you try including the patch and running valgrind? And check for memory leaks? *** ../vim-7.2.069/src/eval.c Tue Dec 9 10:56:50 2008 --- src/eval.c Wed Dec 17 21:32:26 2008 *** *** 32,37 --- 32,40 #define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */ + #define DO_NOT_FREE_CNT 9 /* refcount for dict or list that should not + be freed. */ + /* * In a hashtab item hi_key points to di_key in a dictitem. * This avoids adding a pointer to the hashtab item. *** *** 789,794 --- 792,799 static void func_unref __ARGS((char_u *name)); static void func_ref __ARGS((char_u *name)); static void call_user_func __ARGS((ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict)); + static int can_free_funccal __ARGS((funccall_T *fc, int copyID)) ; + static void free_funccal __ARGS((funccall_T *fc, int free_val)); static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr)); static win_T *find_win_by_nr __ARGS((typval_T *vp, tabpage_T *tp)); static void getwinvar __ARGS((typval_T *argvars, typval_T *rettv, int off)); *** *** 923,928 --- 928,937 /* pointer to funccal for currently active function */ funccall_T *current_funccal = NULL; + /* pointer to list of previously used funccal, still around because some + * item in it is still being used. */ + funccall_T *previous_funccal = NULL; + /* * Return TRUE when a function was ended by a :return command. */ *** *** 6490,6496 buf_T *buf; win_T *wp; int i; ! funccall_T*fc; int did_free = FALSE; #ifdef FEAT_WINDOWS tabpage_T *tp; --- 6499,6505 buf_T *buf; win_T *wp; int i; ! funccall_T*fc, **pfc; int did_free = FALSE; #ifdef FEAT_WINDOWS tabpage_T *tp; *** *** 6574,6579 --- 6583,6602 else ll = ll-lv_used_next; + /* check if any funccal can be freed now */ + for (pfc = previous_funccal; *pfc != NULL; ) + { + if (can_free_funccal(*pfc, copyID)) + { + fc = *pfc; + *pfc = fc-caller; + free_funccal(fc, TRUE); + did_free = TRUE; + } + else + pfc = (*pfc)-caller; + } + return did_free; } *** *** 18962,18968 dictitem_T*dict_var; { hash_init(dict-dv_hashtab); ! dict-dv_refcount = 9; dict_var-di_tv.vval.v_dict = dict; dict_var-di_tv.v_type = VAR_DICT; dict_var-di_tv.v_lock = VAR_FIXED; --- 18985,18991 dictitem_T*dict_var; { hash_init(dict-dv_hashtab); ! dict-dv_refcount = DO_NOT_FREE_CNT; dict_var-di_tv.vval.v_dict = dict; dict_var-di_tv.v_type = VAR_DICT; dict_var-di_tv.v_lock = VAR_FIXED; *** *** 19299,19304 --- 19322,19329 * Copy the values from typval_T from to typval_T to. * When needed allocates string or increases reference count. * Does not make a copy of a list or dict but copies the reference! + * It is OK for from and to to point to the same item. This is used to + * make a copy later. */ static void copy_tv(from, to) *** *** 2,21117 char_u*save_sourcing_name; linenr_T save_sourcing_lnum; scid_Tsave_current_SID; ! funccall_Tfc; int save_did_emsg; static intdepth = 0; dictitem_T*v; --- 21136,21142 char_u*save_sourcing_name; linenr_T save_sourcing_lnum; scid_Tsave_current_SID; ! funccall_T*fc; int save_did_emsg; static intdepth = 0; dictitem_T*v; *** *** 21137,21172 line_breakcheck();/* check for CTRL-C hit */ ! fc.caller = current_funccal; ! current_funccal = fc; ! fc.func = fp; ! fc.rettv = rettv; rettv-vval.v_number = 0; ! fc.linenr = 0; ! fc.returned = FALSE; ! fc.level = ex_nesting_level; /* Check
Re: Bug: E685, SEGV - a:000 garbage collected too early?
Matt Wozniski wrote: function! ReturnArgs(...) return a:000 endfunction Seems to work fine? echo ReturnArgs(1, 2, 3) SEGV echo string(ReturnArgs(1, 2, 3)) function! MakeArgsDict(...) return { 'args': a:000 } endfunction E685 Internal Error echo MakeArgsDict(1, 2, 3) SEGV echo string(MakeArgsDict(1, 2, 3)) For it crashes a while after trying these things. Most likely the reference count for a:000 is wrong. Never thought of someone returning it... -- MONK: ... and the Lord spake, saying, First shalt thou take out the Holy Pin, then shalt thou count to three, no more, no less. Three shalt be the number thou shalt count, and the number of the counting shalt be three. Four shalt thou not count, neither count thou two, excepting that thou then proceed to three. Five is right out. Once the number three, being the third number, be reached, then lobbest thou thy Holy Hand Grenade of Antioch towards thou foe, who being naughty in my sight, shall snuff it. Monty Python and the Holy Grail PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- b...@moolenaar.net -- http://www.Moolenaar.net \\\ ///sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\download, build and distribute -- http://www.A-A-P.org/// \\\help me help AIDS victims -- http://ICCF-Holland.org/// --~--~-~--~~~---~--~~ You received this message from the vim_dev maillist. For more information, visit http://www.vim.org/maillist.php -~--~~~~--~~--~--~---
Re: Bug: E685, SEGV - a:000 garbage collected too early?
2008/12/16 Bram Moolenaar b...@moolenaar.net: Matt Wozniski wrote: function! ReturnArgs(...) return a:000 endfunction Seems to work fine? echo ReturnArgs(1, 2, 3) SEGV echo string(ReturnArgs(1, 2, 3)) function! MakeArgsDict(...) return { 'args': a:000 } endfunction E685 Internal Error echo MakeArgsDict(1, 2, 3) SEGV echo string(MakeArgsDict(1, 2, 3)) For it crashes a while after trying these things. Most likely the reference count for a:000 is wrong. Never thought of someone returning it... When I debugged, I found that v_list was pointing to an invalid address, which had been set in call_user_func() to fc.l_varlist; This variable is in the stack and was only valid while in call_user_func() and the functions it may calls. Somehow, a list still refers to this address after returning from call_user_func() so v_list points then to an invalid address. Making variable fc static (in function call_user_func()) avoids using an invalid address and thus avoids a crash, but it's still not the right way to fix it. Seems to work fine? echo ReturnArgs(1, 2, 3) Actually, even though this appears to work, valgrind memory checker already sees a problem there: ==23275== Invalid read of size 4 ==23275==at 0x809C577: echo_string (eval.c:7232) ==23275==by 0x80AD48C: ex_echo (eval.c:19481) ==23275==by 0x80C71C6: do_one_cmd (ex_docmd.c:2622) ==23275==by 0x80C4A46: do_cmdline (ex_docmd.c:1096) ==23275==by 0x8149D7A: nv_colon (normal.c:5233) ==23275==by 0x81433FE: normal_cmd (normal.c:1200) ==23275==by 0x810678D: main_loop (main.c:1180) ==23275==by 0x81062DA: main (main.c:939) ==23275== Address 0xbef5e280 is not stack'd, malloc'd or (recently) free'd ==23275== ==23275== Invalid write of size 4 ==23275==at 0x809C59D: echo_string (eval.c:7239) ==23275==by 0x80AD48C: ex_echo (eval.c:19481) ==23275==by 0x80C71C6: do_one_cmd (ex_docmd.c:2622) ==23275==by 0x80C4A46: do_cmdline (ex_docmd.c:1096) ==23275==by 0x8149D7A: nv_colon (normal.c:5233) ==23275==by 0x81433FE: normal_cmd (normal.c:1200) ==23275==by 0x810678D: main_loop (main.c:1180) ==23275==by 0x81062DA: main (main.c:939) ==23275== Address 0xbef5e280 is not stack'd, malloc'd or (recently) free'd (etc, more errors to follow) Line eval.c:7232 is: 7232 else if (copyID != 0 tv-vval.v_list-lv_copyID == copyID) 7233 { 7234 *tofree = NULL; 7235 r = (char_u *)[...]; 7236 } 'tv-vval.v_list' points to the invalid address which set as there at line 21193: 21191 v-di_tv.v_type = VAR_LIST; 21192 v-di_tv.v_lock = VAR_FIXED; 21193 v-di_tv.vval.v_list = fc.l_varlist; (fc being a local var in the stack) -- Dominique --~--~-~--~~~---~--~~ You received this message from the vim_dev maillist. For more information, visit http://www.vim.org/maillist.php -~--~~~~--~~--~--~---
Bug: E685, SEGV - a:000 garbage collected too early?
function! ReturnArgs(...) return a:000 endfunction Seems to work fine? echo ReturnArgs(1, 2, 3) SEGV echo string(ReturnArgs(1, 2, 3)) function! MakeArgsDict(...) return { 'args': a:000 } endfunction E685 Internal Error echo MakeArgsDict(1, 2, 3) SEGV echo string(MakeArgsDict(1, 2, 3)) ~Matt --~--~-~--~~~---~--~~ You received this message from the vim_dev maillist. For more information, visit http://www.vim.org/maillist.php -~--~~~~--~~--~--~---
Re: Bug: E685, SEGV - a:000 garbage collected too early?
Matt Wozniski wrote: function! ReturnArgs(...) return a:000 endfunction Seems to work fine? echo ReturnArgs(1, 2, 3) SEGV echo string(ReturnArgs(1, 2, 3)) function! MakeArgsDict(...) return { 'args': a:000 } endfunction E685 Internal Error echo MakeArgsDict(1, 2, 3) SEGV echo string(MakeArgsDict(1, 2, 3)) ~Matt I can reproduce that with vim-7.2.69 on Linux. Following patch seems to fix it, but I'm not sure whether that's the correct fix or whether it's only a workaround: $ cvs diff -c eval.c Index: eval.c === RCS file: /cvsroot/vim/vim7/src/eval.c,v retrieving revision 1.277 diff -c -r1.277 eval.c *** eval.c 9 Dec 2008 09:57:49 - 1.277 --- eval.c 15 Dec 2008 19:39:37 - *** *** 2,21117 char_u*save_sourcing_name; linenr_T save_sourcing_lnum; scid_Tsave_current_SID; ! funccall_Tfc; int save_did_emsg; static intdepth = 0; dictitem_T*v; --- 2,21117 char_u*save_sourcing_name; linenr_T save_sourcing_lnum; scid_Tsave_current_SID; ! static funccall_T fc; int save_did_emsg; static intdepth = 0; dictitem_T*v; -- Dominique --~--~-~--~~~---~--~~ You received this message from the vim_dev maillist. For more information, visit http://www.vim.org/maillist.php -~--~~~~--~~--~--~---
Re: Bug: E685, SEGV - a:000 garbage collected too early?
On Mon, Dec 15, 2008 at 2:42 PM, Dominique Pelle wrote: Matt Wozniski wrote: function! ReturnArgs(...) return a:000 endfunction function! MakeArgsDict(...) return { 'args': a:000 } endfunction I can reproduce that with vim-7.2.69 on Linux. Following patch seems to fix it, but I'm not sure whether that's the correct fix or whether it's only a workaround: That's slightly better, since it no longer seems to crash, but it's still wrong. With that patch applied, combining those two functions - eg, :echo MakeArgsDict(ReturnArgs(1, 2, 3)) gives the completely nonsensical result {'args': [[...]]} when the correct result should be {'args': [1, 2, 3]} Still haven't looked at the source, though, so I can't suggest a better patch yet. ~Matt --~--~-~--~~~---~--~~ You received this message from the vim_dev maillist. For more information, visit http://www.vim.org/maillist.php -~--~~~~--~~--~--~---
Re: Bug: E685, SEGV - a:000 garbage collected too early?
On Mon, Dec 15, 2008 at 4:49 PM, Matt Wozniski wrote: On Mon, Dec 15, 2008 at 2:42 PM, Dominique Pelle wrote: Matt Wozniski wrote: function! ReturnArgs(...) return a:000 endfunction function! MakeArgsDict(...) return { 'args': a:000 } endfunction I can reproduce that with vim-7.2.69 on Linux. Following patch seems to fix it, but I'm not sure whether that's the correct fix or whether it's only a workaround: That's slightly better, since it no longer seems to crash, but it's still wrong. With that patch applied, combining those two functions - eg, :echo MakeArgsDict(ReturnArgs(1, 2, 3)) gives the completely nonsensical result {'args': [[...]]} when the correct result should be {'args': [1, 2, 3]} Still haven't looked at the source, though, so I can't suggest a better patch yet. Better still, :echo string(MakeArgsDict(ReturnArgs(1, 2, 3))) gives E724: variable nested too deep for displaying {'args': } ~Matt --~--~-~--~~~---~--~~ You received this message from the vim_dev maillist. For more information, visit http://www.vim.org/maillist.php -~--~~~~--~~--~--~---