Bram Moolenaar wrote:

> Dominique Pelle wrote:
>
>> 3 remarks about vim/src/undo.c (at changeset: 271a5907f944):
>>
>> (1) Using persistent-undo, I notice once in a while the following memory
>>     leak, but I have not found the way to reproduce it all the time:
>>
>> ==3371== 10 bytes in 2 blocks are definitely lost in loss record 23 of 116
>> ==3371==    at 0x4024F70: malloc (vg_replace_malloc.c:236)
>> ==3371==    by 0x8114F98: lalloc (misc2.c:919)
>> ==3371==    by 0x81BCC06: u_read_undo (undo.c:983)
>> ==3371==    by 0x80C5359: readfile (fileio.c:2591)
>> ==3371==    by 0x8053976: open_buffer (buffer.c:132)
>> ==3371==    by 0x8098ABE: do_ecmd (ex_cmds.c:3658)
>> ==3371==    by 0x80AEF7B: do_exedit (ex_docmd.c:7620)
>> ==3371==    by 0x80AEC38: ex_edit (ex_docmd.c:7516)
>> ==3371==    by 0x80A782C: do_one_cmd (ex_docmd.c:2639)
>> ==3371==    by 0x80A5105: do_cmdline (ex_docmd.c:1108)
>> ==3371==    by 0x812AD39: nv_colon (normal.c:5226)
>> ==3371==    by 0x81245C3: normal_cmd (normal.c:1188)
>> ==3371==    by 0x80E7938: main_loop (main.c:1216)
>> ==3371==    by 0x80E742F: main (main.c:960)
>>
>> It's this alloc in undo.c:
>>
>>  983        array = (char_u **)U_ALLOC_LINE(
>>  984                             (unsigned)(sizeof(char_u *) * 
>> uep->ue_size));
>>
>> Looking at the undo.c code, memory seems to be properly freed
>> but I might be missing something since Valgrind does not generally
>> give spurious leak messages.
>
> The logic is not easy to follow.  Also, there are hardly any checks for
> the undo file to contain invalid information.  I think it's good to
> assume that every value read from the file might be wrong.
>
> I think we need to add more checks that what is read back from the undo
> file is correct.  E.g., when "num_head" is too small the code would
> gladly store pointers beyond the end of uhp_table[].
>
>
>> (2) In vim/src/undo.c  I see at line 92:
>>
>>  91  /* See below: use malloc()/free() for memory management. */
>>  92  #define U_USE_MALLOC 1
>>
>> Whether U_USE_MALLOC is defined or not selects different
>> implementations of U_FREE_LINE and U_ALLOC_LINE.
>>
>> Is the implementation when U_USE_MALLOC is undefined
>> still meant to be used? Or can it be removed?
>>
>> I'm asking because if I comment out the line #define U_USE_MALLOC 1
>> at line undo.c:92, then Vim quickly crashes when using persistent-undo.
>> In other words, persistent undo only works when U_USE_MALLOC is defined.
>
> Can you see why it crashes?  Perhaps it allocates a block that is too
> big?

If I just recompile Vim with "#define U_USE_MALLOC 1" commented out
(without any patch) as follows:

 /* See below: use malloc()/free() for memory management. */
/*#define U_USE_MALLOC 1*/

Then the following command is enough to make Vim crash:

$ vim -u NONE --noplugin -c 'wundo! foo' -c 'rundo foo'
Vim: Caught deadly signal SEGV
Vim: Finished.
Segmentation fault

Program received signal SIGSEGV, Segmentation fault.
0x081bf48c in u_free_line (ptr=0x8264f90 "", keep=0) at undo.c:2846
2846        if ((nextb = curbuf->b_mb_current->mb_next) != NULL
(gdb) bt
#0  0x081bf48c in u_free_line (ptr=0x8264f90 "", keep=0) at undo.c:2846
#1  0x081bc5f0 in u_read_undo (name=0x8264e06 "foo",
    hash=0xbfffed9c
"\343\260\304B\230\374\034\024\232\373\364\310\231o\271$'\256A\344d\233\223L\244\225\231\033xR\270U")
at undo.c:1094
#2  0x080afc34 in ex_rundo (eap=0xbfffedfc) at ex_docmd.c:8481
#3  0x080a70dd in do_one_cmd (cmdlinep=0xbfffefb0, sourcing=1,
cstack=0xbfffefb8, fgetline=0,
    cookie=0x0) at ex_docmd.c:2639
#4  0x080a49b6 in do_cmdline (cmdline=0xbffff6a3 "rundo foo",
getline=0, cookie=0x0, flags=11)
    at ex_docmd.c:1108
#5  0x080a4070 in do_cmdline_cmd (cmd=0xbffff6a3 "rundo foo") at ex_docmd.c:714
#6  0x080e935d in exe_commands (parmp=0xbffff364) at main.c:2750
#7  0x080e6b3a in main (argc=8, argv=0xbffff4e4) at main.c:880
(gdb) list
2841        if (curbuf->b_mb_current == NULL || mp < (minfo_T
*)curbuf->b_mb_current)
2842        {
2843            curbuf->b_mb_current = curbuf->b_block_head.mb_next;
2844            curbuf->b_m_search = NULL;
2845        }
2846        if ((nextb = curbuf->b_mb_current->mb_next) != NULL
2847                                                         && (minfo_T 
*)nextb < mp)
2848        {
2849            curbuf->b_mb_current = nextb;
2850            curbuf->b_m_search = NULL;

(gdb) p curbuf
$1 = (buf_T *) 0x8234dd0
(gdb) p curbuf->b_mb_current
$2 = (mblock_T *) 0x0

So accessing curbuf->b_mb_current->mb_next dereferences NULL.

I have not had time to look at how u_alloc_line() and u_free_line()
work.  Using vim_malloc() and vim_free() is certainly simpler. malloc()
and free() are also quite optimized.  So I don't see the need
for a special implementation.

> I don't think that anybody compiles Vim with U_USE_MALLOC undefined.
> It's probably safe to remove this old code now.
>
>> (3) When U_USE_MALLOC is defined (default behavior), I see that 1 byte
>>     is added to every allocations at line 117:
>>
>>  115 #ifdef U_USE_MALLOC
>>  116 # define U_FREE_LINE(ptr) vim_free(ptr)
>>  117 # define U_ALLOC_LINE(size) lalloc((long_u)((size) + 1), FALSE)
>>  118 #else
>>
>> This extra 1 byte is odd since it's not needed everywhere U_ALLOC_LINE(...)
>> is used.  I think it's better if the caller is responsible for adding +1
>> when needed to avoid wasting memory.  Attached patch does that.
>>
>> Maybe this patch also fixes the leak (1) but I'm not sure since I don't
>> know how to reproduce it all the time.  At least, I have not seen the
>> leak  so far after applying the attached patch.
>
> I don't think it fixes the leak.  It does make it a little bit more
> efficient.
>
> Please test the code with this patch for a while.  I'll include it
> later.

I'll keep using the patch.  So far no problem to report with it.
I'll have more time during the weekend to stress test persistent undo
with & without the patch. It would be nice to find a way to reproduce
the leak.

-- Dominique

-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

Raspunde prin e-mail lui